package mxgateway import ( "fmt" pb "gitea.dohertylan.com/dohertj2/mxaccessgw/clients/go/internal/generated" ) // GatewayError wraps transport-level gRPC failures. type GatewayError struct { Op string Err error } func (e *GatewayError) Error() string { if e == nil { return "" } if e.Op == "" { return fmt.Sprintf("mxgateway: %v", e.Err) } return fmt.Sprintf("mxgateway: %s failed: %v", e.Op, e.Err) } func (e *GatewayError) Unwrap() error { if e == nil { return nil } return e.Err } // CommandError reports a non-OK gateway protocol status and keeps the raw // command reply when one exists. type CommandError struct { Op string Status *ProtocolStatus Reply *MxCommandReply } func (e *CommandError) Error() string { if e == nil { return "" } status := e.Status if status == nil { return fmt.Sprintf("mxgateway: %s failed with missing protocol status", e.Op) } if status.GetMessage() == "" { return fmt.Sprintf("mxgateway: %s failed with protocol status %s", e.Op, status.GetCode()) } return fmt.Sprintf("mxgateway: %s failed with protocol status %s: %s", e.Op, status.GetCode(), status.GetMessage()) } // MxAccessError reports HRESULT or MXSTATUS_PROXY failures returned by MXAccess. type MxAccessError struct { Command *CommandError Reply *MxCommandReply } func (e *MxAccessError) Error() string { if e == nil { return "" } if e.Command != nil && e.Command.Status != nil && e.Command.Status.GetMessage() != "" { return e.Command.Error() } if e.Reply != nil && e.Reply.GetDiagnosticMessage() != "" { return fmt.Sprintf("mxgateway: MXAccess command %s failed: %s", e.Reply.GetKind(), e.Reply.GetDiagnosticMessage()) } if e.Reply != nil && e.Reply.Hresult != nil { return fmt.Sprintf("mxgateway: MXAccess command %s failed with HRESULT 0x%08X", e.Reply.GetKind(), uint32(e.Reply.GetHresult())) } return "mxgateway: MXAccess command failed" } func (e *MxAccessError) Unwrap() error { if e == nil { return nil } return e.Command } // EnsureProtocolSuccess returns a typed CommandError when status is non-OK. func EnsureProtocolSuccess(op string, status *ProtocolStatus, reply *MxCommandReply) error { if status == nil || status.GetCode() == pb.ProtocolStatusCode_PROTOCOL_STATUS_CODE_OK { return nil } commandError := &CommandError{ Op: op, Status: status, Reply: reply, } if status.GetCode() == pb.ProtocolStatusCode_PROTOCOL_STATUS_CODE_MXACCESS_FAILURE { return &MxAccessError{ Command: commandError, Reply: reply, } } return commandError } // EnsureMxAccessSuccess returns a typed MxAccessError for failing HRESULTs or // MXSTATUS_PROXY entries. func EnsureMxAccessSuccess(op string, reply *MxCommandReply) error { if reply == nil { return nil } if reply.Hresult != nil && reply.GetHresult() != 0 { return &MxAccessError{Reply: reply} } for _, status := range reply.GetStatuses() { if !StatusSucceeded(status) { return &MxAccessError{Reply: reply} } } return nil }