cacert-gosigner/client/main.go
Jan Dittberner 80b3309c7c Use better maintained go.bug.st/serial
This commit switches to serial port library to the better maintained
go.bug.st/serial library.
2020-04-17 19:39:06 +02:00

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)
}