|
| 1 | +//! Utilities for supporting custom peer-to-peer messages in LDK. |
| 2 | +//! |
| 3 | +//! [BOLT 1] specifies a custom message type range for use with experimental or application-specific |
| 4 | +//! messages. While a [`CustomMessageHandler`] can be defined to support more than one message type, |
| 5 | +//! defining such a handler requires a significant amount of boilerplate and can be error prone. |
| 6 | +//! |
| 7 | +//! This crate provides the [`composite_custom_message_handler`] macro for easily composing |
| 8 | +//! pre-defined custom message handlers into one handler. The resulting handler can be further |
| 9 | +//! composed with other custom message handlers using the same macro. |
| 10 | +//! |
| 11 | +//! The following example demonstrates defining a `FooBarHandler` to compose separate handlers for |
| 12 | +//! `Foo` and `Bar` messages, and further composing it with a handler for `Baz` messages. |
| 13 | +//! |
| 14 | +//!``` |
| 15 | +//! # extern crate bitcoin; |
| 16 | +//! extern crate lightning; |
| 17 | +//! #[macro_use] |
| 18 | +//! extern crate lightning_custom_message; |
| 19 | +//! |
| 20 | +//! # use bitcoin::secp256k1::PublicKey; |
| 21 | +//! # use lightning::io; |
| 22 | +//! # use lightning::ln::msgs::{DecodeError, LightningError}; |
| 23 | +//! use lightning::ln::peer_handler::CustomMessageHandler; |
| 24 | +//! use lightning::ln::wire::{CustomMessageReader, self}; |
| 25 | +//! use lightning::util::ser::Writeable; |
| 26 | +//! # use lightning::util::ser::Writer; |
| 27 | +//! |
| 28 | +//! // Assume that `FooHandler` and `BarHandler` are defined in one crate and `BazHandler` is |
| 29 | +//! // defined in another crate, handling messages `Foo`, `Bar`, and `Baz`, respectively. |
| 30 | +//! |
| 31 | +//! #[derive(Debug)] |
| 32 | +//! pub struct Foo; |
| 33 | +//! |
| 34 | +//! macro_rules! foo_type_id { |
| 35 | +//! () => { 32768 } |
| 36 | +//! } |
| 37 | +//! |
| 38 | +//! impl wire::Type for Foo { |
| 39 | +//! fn type_id(&self) -> u16 { foo_type_id!() } |
| 40 | +//! } |
| 41 | +//! impl Writeable for Foo { |
| 42 | +//! // ... |
| 43 | +//! # fn write<W: Writer>(&self, _: &mut W) -> Result<(), io::Error> { |
| 44 | +//! # unimplemented!() |
| 45 | +//! # } |
| 46 | +//! } |
| 47 | +//! |
| 48 | +//! pub struct FooHandler; |
| 49 | +//! |
| 50 | +//! impl CustomMessageReader for FooHandler { |
| 51 | +//! // ... |
| 52 | +//! # type CustomMessage = Foo; |
| 53 | +//! # fn read<R: io::Read>( |
| 54 | +//! # &self, _message_type: u16, _buffer: &mut R |
| 55 | +//! # ) -> Result<Option<Self::CustomMessage>, DecodeError> { |
| 56 | +//! # unimplemented!() |
| 57 | +//! # } |
| 58 | +//! } |
| 59 | +//! impl CustomMessageHandler for FooHandler { |
| 60 | +//! // ... |
| 61 | +//! # fn handle_custom_message( |
| 62 | +//! # &self, _msg: Self::CustomMessage, _sender_node_id: &PublicKey |
| 63 | +//! # ) -> Result<(), LightningError> { |
| 64 | +//! # unimplemented!() |
| 65 | +//! # } |
| 66 | +//! # fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Self::CustomMessage)> { |
| 67 | +//! # unimplemented!() |
| 68 | +//! # } |
| 69 | +//! } |
| 70 | +//! |
| 71 | +//! #[derive(Debug)] |
| 72 | +//! pub struct Bar; |
| 73 | +//! |
| 74 | +//! macro_rules! bar_type_id { |
| 75 | +//! () => { 32769 } |
| 76 | +//! } |
| 77 | +//! |
| 78 | +//! impl wire::Type for Bar { |
| 79 | +//! fn type_id(&self) -> u16 { bar_type_id!() } |
| 80 | +//! } |
| 81 | +//! impl Writeable for Bar { |
| 82 | +//! // ... |
| 83 | +//! # fn write<W: Writer>(&self, _: &mut W) -> Result<(), io::Error> { |
| 84 | +//! # unimplemented!() |
| 85 | +//! # } |
| 86 | +//! } |
| 87 | +//! |
| 88 | +//! pub struct BarHandler; |
| 89 | +//! |
| 90 | +//! impl CustomMessageReader for BarHandler { |
| 91 | +//! // ... |
| 92 | +//! # type CustomMessage = Bar; |
| 93 | +//! # fn read<R: io::Read>( |
| 94 | +//! # &self, _message_type: u16, _buffer: &mut R |
| 95 | +//! # ) -> Result<Option<Self::CustomMessage>, DecodeError> { |
| 96 | +//! # unimplemented!() |
| 97 | +//! # } |
| 98 | +//! } |
| 99 | +//! impl CustomMessageHandler for BarHandler { |
| 100 | +//! // ... |
| 101 | +//! # fn handle_custom_message( |
| 102 | +//! # &self, _msg: Self::CustomMessage, _sender_node_id: &PublicKey |
| 103 | +//! # ) -> Result<(), LightningError> { |
| 104 | +//! # unimplemented!() |
| 105 | +//! # } |
| 106 | +//! # fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Self::CustomMessage)> { |
| 107 | +//! # unimplemented!() |
| 108 | +//! # } |
| 109 | +//! } |
| 110 | +//! |
| 111 | +//! #[derive(Debug)] |
| 112 | +//! pub struct Baz; |
| 113 | +//! |
| 114 | +//! macro_rules! baz_type_id { |
| 115 | +//! () => { 32770 } |
| 116 | +//! } |
| 117 | +//! |
| 118 | +//! impl wire::Type for Baz { |
| 119 | +//! fn type_id(&self) -> u16 { baz_type_id!() } |
| 120 | +//! } |
| 121 | +//! impl Writeable for Baz { |
| 122 | +//! // ... |
| 123 | +//! # fn write<W: Writer>(&self, _: &mut W) -> Result<(), io::Error> { |
| 124 | +//! # unimplemented!() |
| 125 | +//! # } |
| 126 | +//! } |
| 127 | +//! |
| 128 | +//! pub struct BazHandler; |
| 129 | +//! |
| 130 | +//! impl CustomMessageReader for BazHandler { |
| 131 | +//! // ... |
| 132 | +//! # type CustomMessage = Baz; |
| 133 | +//! # fn read<R: io::Read>( |
| 134 | +//! # &self, _message_type: u16, _buffer: &mut R |
| 135 | +//! # ) -> Result<Option<Self::CustomMessage>, DecodeError> { |
| 136 | +//! # unimplemented!() |
| 137 | +//! # } |
| 138 | +//! } |
| 139 | +//! impl CustomMessageHandler for BazHandler { |
| 140 | +//! // ... |
| 141 | +//! # fn handle_custom_message( |
| 142 | +//! # &self, _msg: Self::CustomMessage, _sender_node_id: &PublicKey |
| 143 | +//! # ) -> Result<(), LightningError> { |
| 144 | +//! # unimplemented!() |
| 145 | +//! # } |
| 146 | +//! # fn get_and_clear_pending_msg(&self) -> Vec<(PublicKey, Self::CustomMessage)> { |
| 147 | +//! # unimplemented!() |
| 148 | +//! # } |
| 149 | +//! } |
| 150 | +//! |
| 151 | +//! # fn main() { |
| 152 | +//! // The first crate may define a handler composing `FooHandler` and `BarHandler` and export the |
| 153 | +//! // corresponding message type ids as a macro to use in further composition. |
| 154 | +//! |
| 155 | +//! composite_custom_message_handler!( |
| 156 | +//! pub struct FooBarHandler { |
| 157 | +//! foo: FooHandler, |
| 158 | +//! bar: BarHandler, |
| 159 | +//! } |
| 160 | +//! |
| 161 | +//! pub enum FooBarMessage { |
| 162 | +//! Foo(foo_type_id!()), |
| 163 | +//! Bar(bar_type_id!()), |
| 164 | +//! } |
| 165 | +//! ); |
| 166 | +//! |
| 167 | +//! #[macro_export] |
| 168 | +//! macro_rules! foo_bar_type_ids { |
| 169 | +//! () => { foo_type_id!() | bar_type_id!() } |
| 170 | +//! } |
| 171 | +//! |
| 172 | +//! // Another crate can then define a handler further composing `FooBarHandler` with `BazHandler` |
| 173 | +//! // and similarly export the composition of message type ids as a macro. |
| 174 | +//! |
| 175 | +//! composite_custom_message_handler!( |
| 176 | +//! pub struct FooBarBazHandler { |
| 177 | +//! foo_bar: FooBarHandler, |
| 178 | +//! baz: BazHandler, |
| 179 | +//! } |
| 180 | +//! |
| 181 | +//! pub enum FooBarBazMessage { |
| 182 | +//! FooBar(foo_bar_type_ids!()), |
| 183 | +//! Baz(baz_type_id!()), |
| 184 | +//! } |
| 185 | +//! ); |
| 186 | +//! |
| 187 | +//! #[macro_export] |
| 188 | +//! macro_rules! foo_bar_baz_type_ids { |
| 189 | +//! () => { foo_bar_type_ids!() | baz_type_id!() } |
| 190 | +//! } |
| 191 | +//! # } |
| 192 | +//!``` |
| 193 | +//! |
| 194 | +//! [BOLT 1]: https://github.com/lightning/bolts/blob/master/01-messaging.md |
| 195 | +//! [`CustomMessageHandler`]: crate::lightning::ln::peer_handler::CustomMessageHandler |
| 196 | +
|
| 197 | +#![doc(test(no_crate_inject, attr(deny(warnings))))] |
| 198 | + |
| 199 | +pub extern crate bitcoin; |
| 200 | +pub extern crate lightning; |
| 201 | + |
| 202 | +/// Defines a composite type implementing [`CustomMessageHandler`] (and therefore also implementing |
| 203 | +/// [`CustomMessageReader`]), along with a corresponding enumerated custom message [`Type`], from |
| 204 | +/// one or more previously defined custom message handlers. |
| 205 | +/// |
| 206 | +/// Useful for parameterizing [`PeerManager`] with custom message handling for one or more sets of |
| 207 | +/// custom messages. Message type ids may be given as a valid `match` pattern, including ranges, |
| 208 | +/// though using OR-ed literal patterns is preferred in order to catch unreachable code for |
| 209 | +/// conflicting handlers. |
| 210 | +/// |
| 211 | +/// See [crate documentation] for example usage. |
| 212 | +/// |
| 213 | +/// [`CustomMessageHandler`]: crate::lightning::ln::peer_handler::CustomMessageHandler |
| 214 | +/// [`CustomMessageReader`]: crate::lightning::ln::wire::CustomMessageReader |
| 215 | +/// [`Type`]: crate::lightning::ln::wire::Type |
| 216 | +/// [`PeerManager`]: crate::lightning::ln::peer_handler::PeerManager |
| 217 | +/// [crate documentation]: self |
| 218 | +#[macro_export] |
| 219 | +macro_rules! composite_custom_message_handler { |
| 220 | + ( |
| 221 | + $handler_visibility:vis struct $handler:ident { |
| 222 | + $($field_visibility:vis $field:ident: $type:ty),* $(,)* |
| 223 | + } |
| 224 | + |
| 225 | + $message_visibility:vis enum $message:ident { |
| 226 | + $($variant:ident($pattern:pat)),* $(,)* |
| 227 | + } |
| 228 | + ) => { |
| 229 | + #[allow(missing_docs)] |
| 230 | + $handler_visibility struct $handler { |
| 231 | + $( |
| 232 | + $field_visibility $field: $type, |
| 233 | + )* |
| 234 | + } |
| 235 | + |
| 236 | + #[allow(missing_docs)] |
| 237 | + #[derive(Debug)] |
| 238 | + $message_visibility enum $message { |
| 239 | + $( |
| 240 | + $variant(<$type as $crate::lightning::ln::wire::CustomMessageReader>::CustomMessage), |
| 241 | + )* |
| 242 | + } |
| 243 | + |
| 244 | + impl $crate::lightning::ln::peer_handler::CustomMessageHandler for $handler { |
| 245 | + fn handle_custom_message( |
| 246 | + &self, msg: Self::CustomMessage, sender_node_id: &$crate::bitcoin::secp256k1::PublicKey |
| 247 | + ) -> Result<(), $crate::lightning::ln::msgs::LightningError> { |
| 248 | + match msg { |
| 249 | + $( |
| 250 | + $message::$variant(message) => { |
| 251 | + $crate::lightning::ln::peer_handler::CustomMessageHandler::handle_custom_message( |
| 252 | + &self.$field, message, sender_node_id |
| 253 | + ) |
| 254 | + }, |
| 255 | + )* |
| 256 | + } |
| 257 | + } |
| 258 | + |
| 259 | + fn get_and_clear_pending_msg(&self) -> Vec<($crate::bitcoin::secp256k1::PublicKey, Self::CustomMessage)> { |
| 260 | + vec![].into_iter() |
| 261 | + $( |
| 262 | + .chain( |
| 263 | + self.$field |
| 264 | + .get_and_clear_pending_msg() |
| 265 | + .into_iter() |
| 266 | + .map(|(pubkey, message)| (pubkey, $message::$variant(message))) |
| 267 | + ) |
| 268 | + )* |
| 269 | + .collect() |
| 270 | + } |
| 271 | + } |
| 272 | + |
| 273 | + impl $crate::lightning::ln::wire::CustomMessageReader for $handler { |
| 274 | + type CustomMessage = $message; |
| 275 | + fn read<R: $crate::lightning::io::Read>( |
| 276 | + &self, message_type: u16, buffer: &mut R |
| 277 | + ) -> Result<Option<Self::CustomMessage>, $crate::lightning::ln::msgs::DecodeError> { |
| 278 | + match message_type { |
| 279 | + $( |
| 280 | + $pattern => match <$type>::read(&self.$field, message_type, buffer)? { |
| 281 | + None => unreachable!(), |
| 282 | + Some(message) => Ok(Some($message::$variant(message))), |
| 283 | + }, |
| 284 | + )* |
| 285 | + _ => Ok(None), |
| 286 | + } |
| 287 | + } |
| 288 | + } |
| 289 | + |
| 290 | + impl $crate::lightning::ln::wire::Type for $message { |
| 291 | + fn type_id(&self) -> u16 { |
| 292 | + match self { |
| 293 | + $( |
| 294 | + Self::$variant(message) => message.type_id(), |
| 295 | + )* |
| 296 | + } |
| 297 | + } |
| 298 | + } |
| 299 | + |
| 300 | + impl $crate::lightning::util::ser::Writeable for $message { |
| 301 | + fn write<W: $crate::lightning::util::ser::Writer>(&self, writer: &mut W) -> Result<(), $crate::lightning::io::Error> { |
| 302 | + match self { |
| 303 | + $( |
| 304 | + Self::$variant(message) => message.write(writer), |
| 305 | + )* |
| 306 | + } |
| 307 | + } |
| 308 | + } |
| 309 | + } |
| 310 | +} |
0 commit comments