@ -21,6 +21,7 @@ import (
"errors"
"errors"
"fmt"
"fmt"
"sync"
"sync"
"time"
"github.com/shamaton/msgpackgen/msgpack"
"github.com/shamaton/msgpackgen/msgpack"
"github.com/sirupsen/logrus"
"github.com/sirupsen/logrus"
@ -32,185 +33,186 @@ import (
"git.cacert.org/cacert-gosigner/pkg/messages"
"git.cacert.org/cacert-gosigner/pkg/messages"
)
)
// MsgPackHandler is a Handler implementation for the msgpack serialization format.
const readCommandTimeOut = 5 * time . Second
var errReadCommandTimeout = errors . New ( "read command timeout expired" )
// MsgPackHandler is a ServerHandler implementation for the msgpack serialization format.
type MsgPackHandler struct {
type MsgPackHandler struct {
logger * logrus . Logger
logger * logrus . Logger
healthHandler * health . Handler
healthHandler * health . Handler
fetchCRLHandler * revoking . FetchCRLHandler
fetchCRLHandler * revoking . FetchCRLHandler
currentCommand * protocol . Command
currentResponse * protocol . Response
lock sync . Mutex
lock sync . Mutex
}
}
func ( m * MsgPackHandler ) Handle CommandAnnounce( frame [ ] byte ) error {
func ( m * MsgPackHandler ) CommandAnnounce( frame s chan [ ] byte ) ( * protocol . Command , error ) {
m . lock . Lock ( )
m . lock . Lock ( )
defer m . lock . Unlock ( )
defer m . lock . Unlock ( )
frame := <- frames
var ann messages . CommandAnnounce
var ann messages . CommandAnnounce
if err := msgpack . Unmarshal ( frame , & ann ) ; err != nil {
if err := msgpack . Unmarshal ( frame , & ann ) ; err != nil {
return fmt . Errorf ( "could not unmarshal command announcement: %w" , err )
return nil , fmt . Errorf ( "could not unmarshal command announcement: %w" , err )
}
}
m . logger . WithField ( "announcement" , & ann ) . Info ( "received command announcement" )
m . logger . WithField ( "announcement" , & ann ) . Info ( "received command announcement" )
m . currentCommand = & protocol . Command { Announce : & ann }
return & protocol . Command { Announce : & ann } , nil
return nil
}
}
func ( m * MsgPackHandler ) Handle Command( frame [ ] byte ) error {
func ( m * MsgPackHandler ) CommandData ( frame s chan [ ] byte , command * protocol . Command ) error {
m . lock . Lock ( )
m . lock . Lock ( )
defer m . lock . Unlock ( )
defer m . lock . Unlock ( )
err := m . parseCommand ( frame )
select {
case frame := <- frames :
err := m . parseCommand ( frame , command )
if err != nil {
if err != nil {
m . currentResponse = m . buildErrorResponse ( err . Error ( ) )
return err
}
m . logCommandResponse ( )
return nil
return nil
case <- time . After ( readCommandTimeOut ) :
return errReadCommandTimeout
}
}
}
func ( m * MsgPackHandler ) HandleCommand ( command * protocol . Command ) ( * protocol . Response , error ) {
m . lock . Lock ( )
defer m . lock . Unlock ( )
var (
response * protocol . Response
err error
)
err = m . handleCommand ( )
response, err = m . handleCommand ( command )
if err != nil {
if err != nil {
m . logger . WithError ( err ) . Error ( "command handling failed" )
m . logger . WithError ( err ) . Error ( "command handling failed" )
return err
response = m . buildErrorResponse ( command . Announce . ID , "command handling failed" )
}
}
m . logCommandResponse ( )
m . logCommandResponse ( command , response )
m . currentCommand = nil
return response , nil
return nil
}
}
func ( m * MsgPackHandler ) logCommandResponse ( ) {
func ( m * MsgPackHandler ) logCommandResponse ( command * protocol . Command , response * protocol . Response ) {
m . logger . WithField ( "command" , m . currentCommand . Announce ) . Info ( "handled command" )
m . logger . WithField ( "command" , command . Announce ) . Info ( "handled command" )
m . logger . WithField (
m . logger . WithField ( "command" , command ) . WithField ( "response" , response ) . Debug ( "command and response" )
"command" ,
m . currentCommand ,
) . WithField (
"response" ,
m . currentResponse ,
) . Debug ( "command and response" )
}
}
func ( m * MsgPackHandler ) Respon seAnnounce( ) ( [ ] byte , error ) {
func ( m * MsgPackHandler ) Respond ( response * protocol . Response , out chan [ ] byte ) error {
m . lock . Lock ( )
m . lock . Lock ( )
defer m . lock . Unlock ( )
defer m . lock . Unlock ( )
announce Data , err := msgpack . Marshal ( m. cu rrentR esponse. Announc e)
announce , err := msgpack . Marshal ( response)
if err != nil {
if err != nil {
return nil , fmt . Errorf ( "could not marshal response announcement: %w" , err )
return fmt . Errorf ( "could not marshal response announcement: %w" , err )
}
}
m . logger . WithField ( " announcement", m . currentResponse . Announce ) . Debug ( "write response announcement" )
m . logger . WithField ( " length", len ( announce ) ) . Debug ( "write response announcement" )
return announceData , nil
out <- announce
}
func ( m * MsgPackHandler ) ResponseData ( ) ( [ ] byte , error ) {
data , err := msgpack . Marshal ( response . Response )
m . lock . Lock ( )
defer m . lock . Unlock ( )
responseData , err := msgpack . Marshal ( m . currentResponse . Response )
if err != nil {
if err != nil {
return nil , fmt . Errorf ( "could not marshal response: %w" , err )
return fmt . Errorf ( "could not marshal response: %w" , err )
}
}
m . logger . WithField ( "response" , m . currentResponse . Response ) . Debug ( "write response" )
m . logger . WithField ( "length" , len ( data ) ) . Debug ( "write response" )
out <- announce
return responseData , nil
return nil
}
}
func ( m * MsgPackHandler ) parseHealthCommand ( frame [ ] byte ) error {
func ( m * MsgPackHandler ) parseHealthCommand ( frame [ ] byte ) ( * messages . HealthCommand , error ) {
var command messages . HealthCommand
var command messages . HealthCommand
if err := msgpack . Unmarshal ( frame , & command ) ; err != nil {
if err := msgpack . Unmarshal ( frame , & command ) ; err != nil {
m . logger . WithError ( err ) . Error ( "unmarshal failed" )
m . logger . WithError ( err ) . Error ( "unmarshal failed" )
return errors . New ( "could not unmarshal health command" )
return nil , errors . New ( "could not unmarshal health command" )
}
}
m . currentCommand . Command = & command
return & command , nil
return nil
}
}
func ( m * MsgPackHandler ) parseFetchCRLCommand ( frame [ ] byte ) error {
func ( m * MsgPackHandler ) parseFetchCRLCommand ( frame [ ] byte ) ( * messages . FetchCRLCommand , error ) {
var command messages . FetchCRLCommand
var command messages . FetchCRLCommand
if err := msgpack . Unmarshal ( frame , & command ) ; err != nil {
if err := msgpack . Unmarshal ( frame , & command ) ; err != nil {
m . logger . WithError ( err ) . Error ( "unmarshal failed" )
m . logger . WithError ( err ) . Error ( "unmarshal failed" )
return errors . New ( "could not unmarshal fetch crl command" )
return nil , errors . New ( "could not unmarshal fetch crl command" )
}
}
m . currentCommand . Command = & command
return & command , nil
return nil
}
}
func ( m * MsgPackHandler ) currentID ( ) string {
func ( m * MsgPackHandler ) handleCommand ( command * protocol . Command ) ( * protocol . Response , error ) {
return m . currentCommand . Announce . ID
}
func ( m * MsgPackHandler ) handleCommand ( ) error {
var (
var (
err error
responseData interface { }
responseCode messages . ResponseCode
responseCode messages . ResponseCode
responseData interface { }
)
)
switch m. currentC ommand. Command . ( type ) {
switch cmd := c ommand. Command . ( type ) {
case * messages . HealthCommand :
case * messages . HealthCommand :
response , err := m . handleHealthCommand ( )
response , err := m . handleHealthCommand ( )
if err != nil {
if err != nil {
return err
return nil , err
}
}
responseCode , responseData = messages . RespHealth , response
responseCode , responseData = messages . RespHealth , response
case * messages . FetchCRLCommand :
case * messages . FetchCRLCommand :
response , err := m . handleFetchCRLCommand ( )
response , err := m . handleFetchCRLCommand ( cmd )
if err != nil {
if err != nil {
return err
return nil , err
}
}
responseCode , responseData = messages . RespFetchCRL , response
responseCode , responseData = messages . RespFetchCRL , response
default :
default :
return fmt . Errorf ( "unhandled command %s" , m. currentC ommand. Announce )
return nil , fmt . Errorf ( "unhandled command %s" , command. Announce )
}
}
if err != nil {
return & protocol . Response {
return fmt . Errorf ( "error from command handler: %w" , err )
Announce : messages . BuildResponseAnnounce ( responseCode , command . Announce . ID ) ,
}
m . currentResponse = & protocol . Response {
Announce : messages . BuildResponseAnnounce ( responseCode , m . currentID ( ) ) ,
Response : responseData ,
Response : responseData ,
}
} , nil
return nil
}
}
func ( m * MsgPackHandler ) buildErrorResponse ( errMsg string ) * protocol . Response {
func ( m * MsgPackHandler ) buildErrorResponse ( commandID string , errMsg string ) * protocol . Response {
return & protocol . Response {
return & protocol . Response {
Announce : messages . BuildResponseAnnounce ( messages . RespError , m. currentID ( ) ) ,
Announce : messages . BuildResponseAnnounce ( messages . RespError , commandID ) ,
Response : & messages . ErrorResponse { Message : errMsg } ,
Response : & messages . ErrorResponse { Message : errMsg } ,
}
}
}
}
func ( m * MsgPackHandler ) parseCommand ( frame [ ] byte ) error {
func ( m * MsgPackHandler ) parseCommand ( frame [ ] byte , command * protocol . Command ) error {
switch m. currentC ommand. Announce . Code {
switch command. Announce . Code {
case messages . CmdHealth :
case messages . CmdHealth :
return m . parseHealthCommand ( frame )
healthCommand , err := m . parseHealthCommand ( frame )
if err != nil {
return err
}
command . Command = healthCommand
case messages . CmdFetchCRL :
case messages . CmdFetchCRL :
return m . parseFetchCRLCommand ( frame )
fetchCRLCommand , err := m . parseFetchCRLCommand ( frame )
if err != nil {
return err
}
command . Command = fetchCRLCommand
default :
default :
return fmt . Errorf ( "unhandled command code %s" , m . currentCommand . Announce . Code )
return fmt . Errorf ( "unhandled command code %s" , command. Announce . Code )
}
}
return nil
}
}
func ( m * MsgPackHandler ) handleHealthCommand ( ) ( * messages . HealthResponse , error ) {
func ( m * MsgPackHandler ) handleHealthCommand ( ) ( * messages . HealthResponse , error ) {
@ -235,27 +237,20 @@ func (m *MsgPackHandler) handleHealthCommand() (*messages.HealthResponse, error)
return response , nil
return response , nil
}
}
func ( m * MsgPackHandler ) handleFetchCRLCommand ( ) ( * messages . FetchCRLResponse , error ) {
func ( m * MsgPackHandler ) handleFetchCRLCommand ( command * messages . FetchCRLCommand ) ( * messages . FetchCRLResponse , error ) {
fetchCRLPayload , ok := m . currentCommand . Command . ( * messages . FetchCRLCommand )
res , err := m . fetchCRLHandler . FetchCRL ( command . IssuerID )
if ! ok {
return nil , fmt . Errorf ( "could not use payload as FetchCRLPayload" )
}
res , err := m . fetchCRLHandler . FetchCRL ( fetchCRLPayload . IssuerID )
if err != nil {
if err != nil {
return nil , fmt . Errorf ( "could not fetch CRL: %w" , err )
return nil , fmt . Errorf ( "could not fetch CRL: %w" , err )
}
}
response := & messages . FetchCRLResponse {
return & messages . FetchCRLResponse {
IsDelta : false ,
IsDelta : false ,
CRLNumber : res . Number ,
CRLNumber : res . Number ,
CRLData : res . CRLData ,
CRLData : res . CRLData ,
}
} , nil
return response , nil
}
}
func New ( logger * logrus . Logger , handlers ... RegisterHandler ) ( protocol . Handler, error ) {
func New ( logger * logrus . Logger , handlers ... RegisterHandler ) ( protocol . Server Handler, error ) {
messages . RegisterGeneratedResolver ( )
messages . RegisterGeneratedResolver ( )
h := & MsgPackHandler {
h := & MsgPackHandler {