package node import ( "strconv" ) // if protocolError, ok := err.(*ProtocolError); ok { log(protocolError.Code, protocolError.Message) } type ProtocolError struct { Code int Message string } func (protocolError *ProtocolError) Error() string { return "remote error (" + strconv.Itoa(protocolError.Code) + "): " + protocolError.Message } // handler := &ResponseHandler{} // if err := handler.ValidateResponse(resp, MsgPong); err != nil { return 0, err } type ResponseHandler struct{} // if err := handler.ValidateResponse(response, MsgPong); err != nil { return 0, err } func (handler *ResponseHandler) ValidateResponse(response *Message, expectedType MessageType) error { if response == nil { return &ProtocolError{Code: ErrCodeUnknown, Message: "nil response"} } // Check for error response if response.Type == MsgError { var errPayload ErrorPayload if err := response.ParsePayload(&errPayload); err != nil { return &ProtocolError{Code: ErrCodeUnknown, Message: "unable to parse error response"} } return &ProtocolError{Code: errPayload.Code, Message: errPayload.Message} } // Check expected type if response.Type != expectedType { return &ProtocolError{Code: ErrCodeInvalidMessage, Message: "unexpected response type: expected " + string(expectedType) + ", got " + string(response.Type)} } return nil } // var stats StatsPayload // if err := handler.ParseResponse(response, MsgStats, &stats); err != nil { return nil, err } func (handler *ResponseHandler) ParseResponse(response *Message, expectedType MessageType, target interface{}) error { if err := handler.ValidateResponse(response, expectedType); err != nil { return err } if target != nil { if err := response.ParsePayload(target); err != nil { return &ProtocolError{Code: ErrCodeInvalidMessage, Message: "failed to parse " + string(expectedType) + " payload: " + err.Error()} } } return nil } // if err := ValidateResponse(response, MsgPong); err != nil { return 0, err } // delegates to DefaultResponseHandler var DefaultResponseHandler = &ResponseHandler{} // if err := ValidateResponse(response, MsgPong); err != nil { return 0, err } func ValidateResponse(response *Message, expectedType MessageType) error { return DefaultResponseHandler.ValidateResponse(response, expectedType) } // var stats StatsPayload // if err := ParseResponse(response, MsgStats, &stats); err != nil { return nil, err } func ParseResponse(response *Message, expectedType MessageType, target interface{}) error { return DefaultResponseHandler.ParseResponse(response, expectedType, target) } // if node.IsProtocolError(err) { log("remote code:", node.GetProtocolErrorCode(err)) } func IsProtocolError(err error) bool { _, ok := err.(*ProtocolError) return ok } // code := GetProtocolErrorCode(err) // 0 when err is not a ProtocolError func GetProtocolErrorCode(err error) int { if protocolError, ok := err.(*ProtocolError); ok { return protocolError.Code } return 0 }