bitcoincore_zmq/monitor/
event.rs1use super::MonitorMessageError;
2
3trait 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 #[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 #[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}