bitcoincore_zmq/monitor/
event.rs

1use super::MonitorMessageError;
2
3/// Convenience trait to be able to use `from_raw` and `to_raw` on any value that either defines it
4/// or is a `u32`. It doesn't matter that others don't implement this trait, rustc is smart enough
5/// to find that out.
6trait U32Ext: Sized {
7    fn from_raw(value: u32) -> Option<Self>;
8
9    fn to_raw(self) -> u32;
10}
11
12impl U32Ext for u32 {
13    fn from_raw(value: u32) -> Option<Self> {
14        Some(value)
15    }
16
17    fn to_raw(self) -> Self {
18        self
19    }
20}
21
22macro_rules! type_or_u32 {
23    ($type:ty) => {
24        $type
25    };
26    () => {
27        u32
28    };
29}
30
31macro_rules! define_handshake_failure_enum {
32    (
33        $(#[$attr:meta])*
34        $vis:vis enum $enum_name:ident {
35            $(
36                $name:ident = $zmq_sys_name:ident,
37            )*
38        }
39    ) => {
40        $(#[$attr])*
41        $vis enum $enum_name {
42            $(
43                $name = zmq_sys::$zmq_sys_name,
44            )*
45        }
46
47        impl $enum_name {
48            pub const fn from_raw(data: u32) -> Option<Self> {
49                Some(match data {
50                    $(
51                        zmq_sys::$zmq_sys_name => Self::$name,
52                    )*
53                    _ => return None,
54                })
55            }
56
57            pub const fn to_raw(self) -> u32 {
58                self as u32
59            }
60        }
61    };
62}
63
64define_handshake_failure_enum! {
65    /// Possible values for the ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL socket event.
66    #[repr(u32)]
67    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
68    pub enum HandshakeFailure {
69        ZmtpUnspecified = ZMQ_PROTOCOL_ERROR_ZMTP_UNSPECIFIED,
70        ZmtpUnexpectedCommand = ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND,
71        ZmtpInvalidSequence = ZMQ_PROTOCOL_ERROR_ZMTP_INVALID_SEQUENCE,
72        ZmtpKeyExchange = ZMQ_PROTOCOL_ERROR_ZMTP_KEY_EXCHANGE,
73        ZmtpMalformedCommandUnspecified = ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_UNSPECIFIED,
74        ZmtpMalformedCommandMessage = ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_MESSAGE,
75        ZmtpMalformedCommandHello = ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_HELLO,
76        ZmtpMalformedCommandInitiate = ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_INITIATE,
77        ZmtpMalformedCommandError = ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_ERROR,
78        ZmtpMalformedCommandReady = ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_READY,
79        ZmtpMalformedCommandWelcome = ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_WELCOME,
80        ZmtpInvalidMetadata = ZMQ_PROTOCOL_ERROR_ZMTP_INVALID_METADATA,
81        ZmtpCryptographic = ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC,
82        ZmtpMechanismMismatch = ZMQ_PROTOCOL_ERROR_ZMTP_MECHANISM_MISMATCH,
83        ZapUnspecified = ZMQ_PROTOCOL_ERROR_ZAP_UNSPECIFIED,
84        ZapMalformedReply = ZMQ_PROTOCOL_ERROR_ZAP_MALFORMED_REPLY,
85        ZapBadRequestId = ZMQ_PROTOCOL_ERROR_ZAP_BAD_REQUEST_ID,
86        ZapBadVersion = ZMQ_PROTOCOL_ERROR_ZAP_BAD_VERSION,
87        ZapInvalidStatusCode = ZMQ_PROTOCOL_ERROR_ZAP_INVALID_STATUS_CODE,
88        ZapInvalidMetadata = ZMQ_PROTOCOL_ERROR_ZAP_INVALID_METADATA,
89    }
90}
91
92macro_rules! define_socket_event_enum {
93    (
94        $(#[$attr:meta])*
95        $vis:vis enum $enum_name:ident {
96            $(
97                $name:ident $(($value:ident $(: $type:ty)?))? = $zmq_sys_name:ident,
98            )*
99        }
100    ) => {
101        $(#[$attr])*
102        $vis enum $enum_name {
103            $(
104                $name $({ $value: type_or_u32!($($type)?) })?,
105            )*
106            Unknown { event: u16, data: u32 },
107        }
108
109        impl $enum_name {
110            pub fn from_raw(event: u16, data: u32) -> Option<Self> {
111                Some(match event as u32 {
112                    $(
113                        zmq_sys::$zmq_sys_name => Self::$name $({ $value: <type_or_u32!($($type)?)>::from_raw(data)? })?,
114                    )*
115                    _ => Self::Unknown { event, data },
116                })
117            }
118
119            pub fn to_raw(self) -> (u16, Option<u32>) {
120                match self {
121                    $(
122                        Self::$name $({ $value })? => (zmq_sys::$zmq_sys_name as u16, ($(Some($value.to_raw()), )? None::<u32>,).0),
123                    )*
124                    Self::Unknown { event, data } => (event, Some(data)),
125                }
126            }
127        }
128    };
129}
130
131define_socket_event_enum! {
132    /// An event from one of the connected sockets. See the "SUPPORTED EVENTS" section in the
133    /// "zmq_socket_monitor" manual page (`man zmq_socket_monitor`) for the original documentation.
134    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
135    pub enum SocketEvent {
136        Connected(fd) = ZMQ_EVENT_CONNECTED,
137        ConnectDelayed = ZMQ_EVENT_CONNECT_DELAYED,
138        ConnectRetried(interval) = ZMQ_EVENT_CONNECT_RETRIED,
139        Listening(fd) = ZMQ_EVENT_LISTENING,
140        BindFailed(errno) = ZMQ_EVENT_BIND_FAILED,
141        Accepted(fd) = ZMQ_EVENT_ACCEPTED,
142        AcceptFailed(errno) = ZMQ_EVENT_ACCEPT_FAILED,
143        Closed(fd) = ZMQ_EVENT_CLOSED,
144        CloseFailed(errno) = ZMQ_EVENT_CLOSE_FAILED,
145        Disconnected(fd) = ZMQ_EVENT_DISCONNECTED,
146        MonitorStopped = ZMQ_EVENT_MONITOR_STOPPED,
147        HandshakeFailedNoDetail(fd) = ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL,
148        HandshakeSucceeded = ZMQ_EVENT_HANDSHAKE_SUCCEEDED,
149        HandshakeFailedProtocol(err: HandshakeFailure) = ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
150        HandshakeFailedAuth(error_code) = ZMQ_EVENT_HANDSHAKE_FAILED_AUTH,
151    }
152}
153
154impl SocketEvent {
155    pub fn parse_from(msg: &zmq::Message) -> Result<Self, MonitorMessageError> {
156        let bytes = &**msg;
157
158        let event: [u8; 6] = bytes
159            .try_into()
160            .map_err(|_| MonitorMessageError::InvalidEventFrameLength(bytes.len()))?;
161        let event_type = u16::from_ne_bytes(event[0..2].try_into().unwrap());
162        let data = u32::from_ne_bytes(event[2..6].try_into().unwrap());
163
164        Self::from_raw(event_type, data)
165            .ok_or(MonitorMessageError::InvalidEventData(event_type, data))
166    }
167}