99 lines
2.9 KiB
Go
99 lines
2.9 KiB
Go
package node
|
|
|
|
import (
|
|
core "dappco.re/go/core"
|
|
)
|
|
|
|
// ProtocolError represents an error from the remote peer.
|
|
//
|
|
// err := &ProtocolError{Code: ErrorCodeOperationFailed, Message: "start failed"}
|
|
type ProtocolError struct {
|
|
Code int
|
|
Message string
|
|
}
|
|
|
|
func (e *ProtocolError) Error() string {
|
|
return core.Sprintf("remote error (%d): %s", e.Code, e.Message)
|
|
}
|
|
|
|
// ResponseHandler provides helpers for handling protocol responses.
|
|
//
|
|
// handler := &ResponseHandler{}
|
|
type ResponseHandler struct{}
|
|
|
|
// ValidateResponse checks a response against the expected type.
|
|
//
|
|
// err := handler.ValidateResponse(resp, MessageStats)
|
|
func (h *ResponseHandler) ValidateResponse(resp *Message, expectedType MessageType) error {
|
|
if resp == nil {
|
|
return core.E("ResponseHandler.ValidateResponse", "nil response", nil)
|
|
}
|
|
|
|
// Check for error response
|
|
if resp.Type == MessageError {
|
|
var errPayload ErrorPayload
|
|
if err := resp.ParsePayload(&errPayload); err != nil {
|
|
return &ProtocolError{Code: ErrorCodeUnknown, Message: "unable to parse error response"}
|
|
}
|
|
return &ProtocolError{Code: errPayload.Code, Message: errPayload.Message}
|
|
}
|
|
|
|
// Check expected type
|
|
if resp.Type != expectedType {
|
|
return core.E("ResponseHandler.ValidateResponse", "unexpected response type: expected "+string(expectedType)+", got "+string(resp.Type), nil)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ParseResponse validates the response and parses the payload into the target.
|
|
//
|
|
// err := handler.ParseResponse(resp, MessageStats, &stats)
|
|
func (h *ResponseHandler) ParseResponse(resp *Message, expectedType MessageType, target any) error {
|
|
if err := h.ValidateResponse(resp, expectedType); err != nil {
|
|
return err
|
|
}
|
|
|
|
if target != nil {
|
|
if err := resp.ParsePayload(target); err != nil {
|
|
return core.E("ResponseHandler.ParseResponse", "failed to parse "+string(expectedType)+" payload", err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// handler := DefaultResponseHandler
|
|
var DefaultResponseHandler = &ResponseHandler{}
|
|
|
|
// ValidateResponse is a convenience function using the default handler.
|
|
//
|
|
// err := ValidateResponse(message, MessageStats)
|
|
func ValidateResponse(resp *Message, expectedType MessageType) error {
|
|
return DefaultResponseHandler.ValidateResponse(resp, expectedType)
|
|
}
|
|
|
|
// ParseResponse is a convenience function using the default handler.
|
|
//
|
|
// err := ParseResponse(message, MessageStats, &stats)
|
|
func ParseResponse(resp *Message, expectedType MessageType, target any) error {
|
|
return DefaultResponseHandler.ParseResponse(resp, expectedType, target)
|
|
}
|
|
|
|
// IsProtocolError returns true if the error is a ProtocolError.
|
|
//
|
|
// ok := IsProtocolError(err)
|
|
func IsProtocolError(err error) bool {
|
|
_, ok := err.(*ProtocolError)
|
|
return ok
|
|
}
|
|
|
|
// GetProtocolErrorCode returns the error code if err is a ProtocolError, otherwise returns 0.
|
|
//
|
|
// code := GetProtocolErrorCode(err)
|
|
func GetProtocolErrorCode(err error) int {
|
|
if pe, ok := err.(*ProtocolError); ok {
|
|
return pe.Code
|
|
}
|
|
return 0
|
|
}
|