package main import ( "flag" "os" "os/signal" "sync" "syscall" "time" log "github.com/sirupsen/logrus" "go.bug.st/serial" "git.cacert.org/cacert-gosigner/client/processing" "git.cacert.org/cacert-gosigner/client/protocol" "git.cacert.org/cacert-gosigner/datastructures" ) const mainLoopSleep = 2700 func main() { var configFile string flag.StringVar(&configFile, "c", "client.yaml", "client configuration file in YAML format") flag.Parse() var ( clientConfig *ClientConfig serialConfig *serial.Mode err error ) if clientConfig, err = readConfig(configFile); err != nil { log.Panic(err) } serialConfig = fillSerialMode(clientConfig) if clientConfig.Debug { log.SetLevel(log.TraceLevel) } 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") requestChannel := protocol.NewSignerProtocolRequestChannel() responseChannel := make(chan *datastructures.SignerResponse, 1) clientProtocolConfig := protocol.NewSignerProtocolConfig() if clientConfig.BufferSize != 0 { clientProtocolConfig.BufferSize = int(clientConfig.BufferSize) } protocolHandler := protocol.NewProtocolHandler( requestChannel, &responseChannel, port, clientProtocolConfig, ) cancelChannel := make(chan os.Signal, 1) signal.Notify(cancelChannel, syscall.SIGTERM, syscall.SIGINT) const goRoutines = 2 wg := sync.WaitGroup{} wg.Add(goRoutines) go func() { if err := protocolHandler.HandleSignerProtocol(); err != nil { log.Errorf("terminating because of %v", err) close(cancelChannel) } wg.Done() }() go func() { runMainLoop(requestChannel, &responseChannel) wg.Done() }() sig := <-cancelChannel if sig != nil { log.Infof("caught %+v", sig) } if err := protocolHandler.Close(); err != nil { log.Error(err) } else { log.Infof("protocol handler closed") } if err := port.Close(); err != nil { log.Error(err) } else { log.Infof("serial port closed") } wg.Wait() } func runMainLoop( requestChannel *protocol.SignerProtocolRequestChannel, responseChannel *chan *datastructures.SignerResponse, ) { crlCheck := 0 log.Debug("starting main loop") go func() { for response := range *responseChannel { if err := processing.Process(response); err != nil { log.Error(err) } } log.Trace("processing goroutine terminated") }() for { 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) } if requestChannel.IsClosed() { return } log.Debug("send NUL request to keep connection open") requestChannel.C <- datastructures.NewNulRequest() log.Debug("sleep for 2.7 seconds") time.Sleep(mainLoopSleep * time.Millisecond) } }