2025-12-31 12:43:46 +00:00
|
|
|
package node
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
)
|
|
|
|
|
|
2026-04-02 08:20:07 +01:00
|
|
|
// if pe, ok := err.(*ProtocolError); ok { log(pe.Code, pe.Message) }
|
2025-12-31 12:43:46 +00:00
|
|
|
type ProtocolError struct {
|
|
|
|
|
Code int
|
|
|
|
|
Message string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (e *ProtocolError) Error() string {
|
|
|
|
|
return fmt.Sprintf("remote error (%d): %s", e.Code, e.Message)
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-02 08:20:07 +01:00
|
|
|
// handler := &ResponseHandler{}
|
|
|
|
|
// if err := handler.ValidateResponse(resp, MsgPong); err != nil { return 0, err }
|
2025-12-31 12:43:46 +00:00
|
|
|
type ResponseHandler struct{}
|
|
|
|
|
|
2026-04-02 07:47:37 +01:00
|
|
|
// if err := handler.ValidateResponse(resp, MsgPong); err != nil { return 0, err }
|
2025-12-31 12:43:46 +00:00
|
|
|
func (h *ResponseHandler) ValidateResponse(resp *Message, expectedType MessageType) error {
|
|
|
|
|
if resp == nil {
|
|
|
|
|
return fmt.Errorf("nil response")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check for error response
|
|
|
|
|
if resp.Type == MsgError {
|
|
|
|
|
var errPayload ErrorPayload
|
|
|
|
|
if err := resp.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 resp.Type != expectedType {
|
|
|
|
|
return fmt.Errorf("unexpected response type: expected %s, got %s", expectedType, resp.Type)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-02 09:34:58 +01:00
|
|
|
// var stats StatsPayload
|
|
|
|
|
// if err := handler.ParseResponse(resp, MsgStats, &stats); err != nil { return nil, err }
|
2025-12-31 12:43:46 +00:00
|
|
|
func (h *ResponseHandler) ParseResponse(resp *Message, expectedType MessageType, target interface{}) error {
|
|
|
|
|
if err := h.ValidateResponse(resp, expectedType); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if target != nil {
|
|
|
|
|
if err := resp.ParsePayload(target); err != nil {
|
|
|
|
|
return fmt.Errorf("failed to parse %s payload: %w", expectedType, err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// DefaultResponseHandler is the default response handler instance.
|
|
|
|
|
var DefaultResponseHandler = &ResponseHandler{}
|
|
|
|
|
|
2026-04-02 10:28:54 +01:00
|
|
|
// if err := ValidateResponse(resp, MsgPong); err != nil { return 0, err }
|
2025-12-31 12:43:46 +00:00
|
|
|
func ValidateResponse(resp *Message, expectedType MessageType) error {
|
|
|
|
|
return DefaultResponseHandler.ValidateResponse(resp, expectedType)
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-02 10:28:54 +01:00
|
|
|
// var stats StatsPayload
|
|
|
|
|
// if err := ParseResponse(resp, MsgStats, &stats); err != nil { return nil, err }
|
2025-12-31 12:43:46 +00:00
|
|
|
func ParseResponse(resp *Message, expectedType MessageType, target interface{}) error {
|
|
|
|
|
return DefaultResponseHandler.ParseResponse(resp, expectedType, target)
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-02 08:37:09 +01:00
|
|
|
// if node.IsProtocolError(err) { log("remote code:", node.GetProtocolErrorCode(err)) }
|
2025-12-31 12:43:46 +00:00
|
|
|
func IsProtocolError(err error) bool {
|
|
|
|
|
_, ok := err.(*ProtocolError)
|
|
|
|
|
return ok
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-02 10:28:54 +01:00
|
|
|
// code := GetProtocolErrorCode(err) // 0 when err is not a ProtocolError
|
2025-12-31 12:43:46 +00:00
|
|
|
func GetProtocolErrorCode(err error) int {
|
|
|
|
|
if pe, ok := err.(*ProtocolError); ok {
|
|
|
|
|
return pe.Code
|
|
|
|
|
}
|
|
|
|
|
return 0
|
|
|
|
|
}
|