80b3309c7c
This commit switches to serial port library to the better maintained go.bug.st/serial library.
150 lines
3.7 KiB
Go
150 lines
3.7 KiB
Go
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"time"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
"go.bug.st/serial"
|
|
|
|
"git.cacert.org/cacert-gosigner/datastructures"
|
|
"git.cacert.org/cacert-gosigner/shared"
|
|
)
|
|
|
|
func main() {
|
|
var configFile string
|
|
|
|
flag.StringVar(&configFile, "c", "client.yaml", "client configuration file in YAML format")
|
|
flag.Parse()
|
|
|
|
var clientConfig *ClientConfig
|
|
var serialConfig *serial.Mode
|
|
var err error
|
|
|
|
if clientConfig, err = readConfig(configFile); err != nil {
|
|
log.Panic(err)
|
|
}
|
|
serialConfig = fillSerialMode(clientConfig)
|
|
if clientConfig.Debug {
|
|
log.SetLevel(log.DebugLevel)
|
|
}
|
|
|
|
log.Infof("connecting to %s using %+v", clientConfig.SerialAddress, serialConfig)
|
|
port, err := serial.Open(clientConfig.SerialAddress, serialConfig)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
log.Debug("serial port connected")
|
|
defer func() {
|
|
err := port.Close()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
log.Debug("serial port closed")
|
|
}()
|
|
|
|
errorChannel := make(chan error, 1)
|
|
responseChannel := make(chan datastructures.SignerResponse, 1)
|
|
crlCheck := 0
|
|
|
|
log.Debug("starting main loop")
|
|
|
|
for {
|
|
requestChannel := make(chan datastructures.SignerRequest, 1)
|
|
|
|
go HandleRequests(&port, &responseChannel, &errorChannel, &requestChannel)
|
|
|
|
log.Debug("handling GPG database ...")
|
|
// HandleGPG(&requestChannel)
|
|
log.Debug("issuing certificates ...")
|
|
// HandleCertificates(&requestChannel)
|
|
log.Debug("revoking certificates ...")
|
|
// RevokeCertificates(&requestChannel)
|
|
|
|
crlCheck++
|
|
if crlCheck%100 == 0 {
|
|
log.Debug("refresh CRLs ...")
|
|
// RefreshCRLs(&requestChannel)
|
|
}
|
|
|
|
log.Debug("send NUL request to keep connection open")
|
|
requestChannel <- *datastructures.NewNulRequest()
|
|
|
|
select {
|
|
case response := <-responseChannel:
|
|
if err := Process(response); err != nil {
|
|
log.Error(err)
|
|
}
|
|
case err := <-errorChannel:
|
|
log.Error(err)
|
|
}
|
|
|
|
log.Debug("sleep for 2.7 seconds")
|
|
time.Sleep(2700 * time.Millisecond)
|
|
}
|
|
}
|
|
|
|
func Process(response datastructures.SignerResponse) (err error) {
|
|
log.Infof("process response of type %s", response.Action)
|
|
log.Tracef("process response %v", response)
|
|
|
|
switch response.Action {
|
|
case datastructures.ActionNul:
|
|
log.Trace("received response for NUL request")
|
|
return
|
|
default:
|
|
return fmt.Errorf("unsupported action in response 0x%x", response.Action)
|
|
}
|
|
}
|
|
|
|
func HandleRequests(port *serial.Port, responseChan *chan datastructures.SignerResponse, errorChan *chan error, requestChan *chan datastructures.SignerRequest) {
|
|
for {
|
|
select {
|
|
case request := <-*requestChan:
|
|
SendRequest(port, responseChan, errorChan, &request)
|
|
}
|
|
}
|
|
}
|
|
|
|
func SendRequest(port *serial.Port, responseChan *chan datastructures.SignerResponse, errorChan *chan error, request *datastructures.SignerRequest) {
|
|
log.Tracef("send request %v to serial port %v", *request, *port)
|
|
if err := sendHandShake(*port); err != nil {
|
|
*errorChan <- err
|
|
return
|
|
}
|
|
|
|
requestBytes := request.Serialize()
|
|
if length, err := (*port).Write(requestBytes); err != nil {
|
|
*errorChan <- err
|
|
return
|
|
} else {
|
|
log.Tracef("wrote %d request bytes", length)
|
|
}
|
|
|
|
if length, err := (*port).Write([]byte{datastructures.CalculateXorCheckSum([][]byte{requestBytes})}); err != nil {
|
|
*errorChan <- err
|
|
return
|
|
} else {
|
|
log.Tracef("wrote %d checksum bytes", length)
|
|
}
|
|
|
|
if length, err := (*port).Write([]byte(shared.MagicTrailer)); err != nil {
|
|
*errorChan <- err
|
|
return
|
|
} else {
|
|
log.Tracef("wrote %d trailer bytes", length)
|
|
}
|
|
|
|
header, err := shared.ReceiveBytes(port, 1, 20)
|
|
if err != nil {
|
|
*errorChan <- err
|
|
return
|
|
}
|
|
if header[0] != shared.AckByte {
|
|
*errorChan <- fmt.Errorf("unexpected byte 0x%x expected 0x%x", header, shared.AckByte)
|
|
return
|
|
}
|
|
|
|
receiveResponse(port, responseChan, errorChan)
|
|
}
|