go-p2p/node/protocol.go
Virgil c678d20608 refactor(repo): prefer AX error names
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-30 19:44:05 +00:00

100 lines
3.1 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 if the response is valid and returns a parsed error if it's an error response.
// It checks:
// 1. If response is nil (returns error)
// 2. If response is an error message (returns ProtocolError)
// 3. If response type matches expected (returns error if not)
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 == MsgError {
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.
// This combines ValidateResponse and ParsePayload into a single call.
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
}
// DefaultResponseHandler is the default response handler instance.
var DefaultResponseHandler = &ResponseHandler{}
// ValidateResponse is a convenience function using the default handler.
//
// err := ValidateResponse(msg, MsgStats)
func ValidateResponse(resp *Message, expectedType MessageType) error {
return DefaultResponseHandler.ValidateResponse(resp, expectedType)
}
// ParseResponse is a convenience function using the default handler.
//
// err := ParseResponse(msg, MsgStats, &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
}