Improve signer robustness

- let client simulator send some garbage bytes before starting real commands
- handle EOF during reads
This commit is contained in:
Jan Dittberner 2022-11-29 10:29:09 +01:00
parent e5dcf7afa9
commit 9905d748d9
2 changed files with 72 additions and 32 deletions

View file

@ -21,7 +21,9 @@ package main
import ( import (
"context" "context"
"crypto/rand"
"fmt" "fmt"
"io"
"os" "os"
"sync" "sync"
"time" "time"
@ -155,16 +157,27 @@ func (g *TestCommandGenerator) HandleResponse(frame []byte) error {
} }
func (g *TestCommandGenerator) GenerateCommands(ctx context.Context) error { func (g *TestCommandGenerator) GenerateCommands(ctx context.Context) error {
const (
healthInterval = 5 * time.Second
startPause = 3 * time.Second
)
var ( var (
announce *messages.CommandAnnounce announce *messages.CommandAnnounce
err error err error
) )
// write some leading garbage to test signer robustness
_, _ = io.CopyN(os.Stdout, rand.Reader, 50) //nolint:gomnd
announce, err = messages.BuildCommandAnnounce(messages.CmdHealth)
if err != nil {
return fmt.Errorf("build command announce failed: %w", err)
}
g.commands <- &protocol.Command{Announce: announce, Command: &messages.HealthCommand{}}
const (
healthInterval = 5 * time.Second
crlInterval = 15 * time.Minute
startPause = 3 * time.Second
)
g.logger.Info("start generating commands") g.logger.Info("start generating commands")
time.Sleep(startPause) time.Sleep(startPause)
@ -179,17 +192,18 @@ func (g *TestCommandGenerator) GenerateCommands(ctx context.Context) error {
Command: &messages.FetchCRLCommand{IssuerID: "sub-ecc_person_2022"}, Command: &messages.FetchCRLCommand{IssuerID: "sub-ecc_person_2022"},
} }
timer := time.NewTimer(healthInterval) healthTimer := time.NewTimer(healthInterval)
crlTimer := time.NewTimer(crlInterval)
for { for {
select { select {
case <-ctx.Done(): case <-ctx.Done():
_ = timer.Stop() _ = healthTimer.Stop()
g.logger.Info("stopping health check loop") g.logger.Info("stopping health check loop")
return nil return nil
case <-timer.C: case <-healthTimer.C:
announce, err = messages.BuildCommandAnnounce(messages.CmdHealth) announce, err = messages.BuildCommandAnnounce(messages.CmdHealth)
if err != nil { if err != nil {
return fmt.Errorf("build command announce failed: %w", err) return fmt.Errorf("build command announce failed: %w", err)
@ -199,9 +213,14 @@ func (g *TestCommandGenerator) GenerateCommands(ctx context.Context) error {
Announce: announce, Announce: announce,
Command: &messages.HealthCommand{}, Command: &messages.HealthCommand{},
} }
}
timer.Reset(healthInterval) healthTimer.Reset(healthInterval)
case <-crlTimer.C:
g.commands <- &protocol.Command{
Announce: announce,
Command: &messages.FetchCRLCommand{IssuerID: "sub-ecc_person_2022"},
}
}
} }
} }
@ -249,11 +268,14 @@ func (c *clientSimulator) writeCommand() error {
return nil return nil
} }
const responseAnnounceTimeout = 30 * time.Second
const responseDataTimeout = 2 * time.Second
func (c *clientSimulator) handleResponseAnnounce() error { func (c *clientSimulator) handleResponseAnnounce() error {
c.logger.Trace("waiting for response announce") c.logger.Trace("waiting for response announce")
frame := <-c.framesIn select {
case frame := <-c.framesIn:
if frame == nil { if frame == nil {
return nil return nil
} }
@ -265,6 +287,13 @@ func (c *clientSimulator) handleResponseAnnounce() error {
if err := c.nextState(); err != nil { if err := c.nextState(); err != nil {
return err return err
} }
case <-time.After(responseAnnounceTimeout):
c.logger.Warn("response announce timeout expired")
c.protocolState = cmdAnnounce
return nil
}
return nil return nil
} }
@ -272,8 +301,8 @@ func (c *clientSimulator) handleResponseAnnounce() error {
func (c *clientSimulator) handleResponseData() error { func (c *clientSimulator) handleResponseData() error {
c.logger.Trace("waiting for response data") c.logger.Trace("waiting for response data")
frame := <-c.framesIn select {
case frame := <-c.framesIn:
if frame == nil { if frame == nil {
return nil return nil
} }
@ -287,6 +316,13 @@ func (c *clientSimulator) handleResponseData() error {
} }
return nil return nil
case <-time.After(responseDataTimeout):
c.logger.Warn("response data timeout expired")
c.protocolState = cmdAnnounce
return nil
}
} }
func (c *clientSimulator) Run(ctx context.Context) error { func (c *clientSimulator) Run(ctx context.Context) error {

View file

@ -146,6 +146,10 @@ func (c *COBSFramer) readRaw(reader io.Reader) ([]byte, error) {
count, err := reader.Read(buf) count, err := reader.Read(buf)
if err != nil { if err != nil {
if errors.Is(err, io.EOF) {
return []byte{}, nil
}
return nil, fmt.Errorf("could not read data: %w", err) return nil, fmt.Errorf("could not read data: %w", err)
} }