fix read_qr command lock

This commit is contained in:
programmer10110 2020-10-28 16:25:06 +03:00
parent 584b855ecf
commit 3bbc442955
3 changed files with 66 additions and 37 deletions

View File

@ -78,6 +78,10 @@ func (am *Machine) SetQRProcessorFramesDelay(delay int) {
am.qrProcessor.SetDelay(delay) am.qrProcessor.SetDelay(delay)
} }
func (am *Machine) CloseCameraReader() {
am.qrProcessor.CloseCameraReader()
}
func (am *Machine) SetQRProcessorChunkSize(chunkSize int) { func (am *Machine) SetQRProcessorChunkSize(chunkSize int) {
am.qrProcessor.SetChunkSize(chunkSize) am.qrProcessor.SetChunkSize(chunkSize)
} }

View File

@ -33,10 +33,12 @@ type terminal struct {
reader *bufio.Reader reader *bufio.Reader
airgapped *airgapped.Machine airgapped *airgapped.Machine
commands map[string]*terminalCommand commands map[string]*terminalCommand
currentCommand string
} }
func NewTerminal(machine *airgapped.Machine) *terminal { func NewTerminal(machine *airgapped.Machine) *terminal {
t := terminal{bufio.NewReader(os.Stdin), machine, make(map[string]*terminalCommand)} t := terminal{bufio.NewReader(os.Stdin), machine, make(map[string]*terminalCommand), ""}
t.addCommand("read_qr", &terminalCommand{ t.addCommand("read_qr", &terminalCommand{
commandHandler: t.readQRCommand, commandHandler: t.readQRCommand,
description: "Reads QR chunks from camera, handle a decoded operation and returns paths to qr chunks of operation's result", description: "Reads QR chunks from camera, handle a decoded operation and returns paths to qr chunks of operation's result",
@ -229,7 +231,9 @@ func (t *terminal) run() error {
if err != nil { if err != nil {
return fmt.Errorf("failed to read command: %w", err) return fmt.Errorf("failed to read command: %w", err)
} }
handler, ok := t.commands[strings.Trim(command, "\n")]
clearCommand := strings.Trim(command, "\n")
handler, ok := t.commands[clearCommand]
if !ok { if !ok {
fmt.Printf("unknown command: %s\n", command) fmt.Printf("unknown command: %s\n", command)
continue continue
@ -238,11 +242,12 @@ func (t *terminal) run() error {
return err return err
} }
t.airgapped.Lock() t.airgapped.Lock()
t.currentCommand = clearCommand
if err := handler.commandHandler(); err != nil { if err := handler.commandHandler(); err != nil {
fmt.Printf("failled to execute command %s: %v \n", command, err) fmt.Printf("failled to execute command %s: %v \n", command, err)
t.airgapped.Unlock()
continue
} }
t.currentCommand = ""
t.airgapped.Unlock() t.airgapped.Unlock()
} }
} }
@ -288,14 +293,19 @@ func main() {
c := make(chan os.Signal, 1) c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt) signal.Notify(c, os.Interrupt)
t := NewTerminal(air)
go t.dropSensitiveData(passwordLifeDuration)
go func() { go func() {
for range c { for range c {
if t.currentCommand == "read_qr" {
t.airgapped.CloseCameraReader()
continue
}
fmt.Printf("Intercepting SIGINT, please type `exit` to stop the machine\n>>> ") fmt.Printf("Intercepting SIGINT, please type `exit` to stop the machine\n>>> ")
} }
}() }()
t := NewTerminal(air)
go t.dropSensitiveData(passwordLifeDuration)
if err = t.run(); err != nil { if err = t.run(); err != nil {
log.Fatalf(err.Error()) log.Fatalf(err.Error())
} }

View File

@ -30,15 +30,24 @@ type Processor interface {
WriteQR(path string, data []byte) error WriteQR(path string, data []byte) error
SetDelay(delay int) SetDelay(delay int)
SetChunkSize(chunkSize int) SetChunkSize(chunkSize int)
CloseCameraReader()
} }
type CameraProcessor struct { type CameraProcessor struct {
gifFramesDelay int gifFramesDelay int
chunkSize int chunkSize int
closeCameraReader chan bool
} }
func NewCameraProcessor() *CameraProcessor { func NewCameraProcessor() Processor {
return &CameraProcessor{} return &CameraProcessor{
closeCameraReader: make(chan bool),
}
}
func (p *CameraProcessor) CloseCameraReader() {
p.closeCameraReader <- true
} }
func (p *CameraProcessor) SetDelay(delay int) { func (p *CameraProcessor) SetDelay(delay int) {
@ -73,37 +82,43 @@ func (p *CameraProcessor) ReadQR() ([]byte, error) {
chunks := make([]*chunk, 0) chunks := make([]*chunk, 0)
decodedChunksCount := uint(0) decodedChunksCount := uint(0)
// detects and scans QR-cods from camera until we scan successfully // detects and scans QR-cods from camera until we scan successfully
READER:
for { for {
webcam.Read(&img) select {
window.IMShow(img) case <-p.closeCameraReader:
window.WaitKey(1) return nil, fmt.Errorf("camera reader was closed")
default:
webcam.Read(&img)
window.IMShow(img)
window.WaitKey(1)
imgObject, err := img.ToImage() imgObject, err := img.ToImage()
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to get image object: %w", err) return nil, fmt.Errorf("failed to get image object: %w", err)
} }
data, err := ReadDataFromQR(imgObject) data, err := ReadDataFromQR(imgObject)
if err != nil { if err != nil {
continue continue
} }
decodedChunk, err := decodeChunk(data) decodedChunk, err := decodeChunk(data)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if cap(chunks) == 0 { if cap(chunks) == 0 {
chunks = make([]*chunk, decodedChunk.Total) chunks = make([]*chunk, decodedChunk.Total)
} }
if decodedChunk.Index > decodedChunk.Total { if decodedChunk.Index > decodedChunk.Total {
return nil, fmt.Errorf("invalid QR-code chunk") return nil, fmt.Errorf("invalid QR-code chunk")
} }
if chunks[decodedChunk.Index] != nil { if chunks[decodedChunk.Index] != nil {
continue continue
} }
chunks[decodedChunk.Index] = decodedChunk chunks[decodedChunk.Index] = decodedChunk
decodedChunksCount++ decodedChunksCount++
window.SetWindowTitle(fmt.Sprintf("Read %d/%d chunks", decodedChunksCount, decodedChunk.Total)) window.SetWindowTitle(fmt.Sprintf("Read %d/%d chunks", decodedChunksCount, decodedChunk.Total))
if decodedChunksCount == decodedChunk.Total { if decodedChunksCount == decodedChunk.Total {
break break READER
}
} }
} }
window.SetWindowTitle("QR-code chunks successfully read!") window.SetWindowTitle("QR-code chunks successfully read!")