message.rs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2025 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use std::net::Ipv6Addr;
  19. use darkfi_serial::{
  20. async_trait, serialize_async, AsyncDecodable, AsyncEncodable, SerialDecodable, SerialEncodable,
  21. };
  22. use url::{Host, Url};
  23. use crate::{net::metering::MeteringConfiguration, util::time::NanoTimestamp};
  24. /// Generic message template.
  25. pub trait Message: 'static + Send + Sync + AsyncDecodable + AsyncEncodable {
  26. const NAME: &'static str;
  27. /// Message bytes vector length limit.
  28. /// Set to 0 for no limit.
  29. const MAX_BYTES: u64;
  30. /// Message metering score value.
  31. /// Set to 0 for no impact in metering.
  32. const METERING_SCORE: u64;
  33. /// Message metering configuration for rate limit.
  34. /// Use `MeteringConfiguration::default()` for no limit.
  35. const METERING_CONFIGURATION: MeteringConfiguration;
  36. }
  37. /// Generic serialized message template.
  38. pub struct SerializedMessage {
  39. pub command: String,
  40. pub payload: Vec<u8>,
  41. }
  42. impl SerializedMessage {
  43. pub async fn new<M: Message>(message: &M) -> Self {
  44. Self { command: M::NAME.to_string(), payload: serialize_async(message).await }
  45. }
  46. }
  47. #[macro_export]
  48. macro_rules! impl_p2p_message {
  49. ($st:ty, $nm:expr, $mb:expr, $ms:expr, $mc:expr) => {
  50. impl Message for $st {
  51. const NAME: &'static str = $nm;
  52. const MAX_BYTES: u64 = $mb;
  53. const METERING_SCORE: u64 = $ms;
  54. const METERING_CONFIGURATION: MeteringConfiguration = $mc;
  55. }
  56. };
  57. }
  58. /// Maximum command (message name) length in bytes
  59. pub const MAX_COMMAND_LENGTH: u8 = 255;
  60. /// For each message configs a threshold was calculated by taking the maximum number of messages
  61. /// in a 10 seconds window and multiply it by 2 not to be strict.
  62. pub const PING_PONG_METERING_CONFIGURATION: MeteringConfiguration = MeteringConfiguration {
  63. threshold: 4,
  64. sleep_step: 1000,
  65. expiry_time: NanoTimestamp::from_secs(10),
  66. };
  67. /// Ping-Pong messages fields size
  68. /// * nonce = 2
  69. pub const PING_PONG_MAX_BYTES: u64 = 2;
  70. /// Outbound keepalive message.
  71. #[derive(Debug, Copy, Clone, SerialEncodable, SerialDecodable)]
  72. pub struct PingMessage {
  73. pub nonce: u16,
  74. }
  75. impl_p2p_message!(PingMessage, "ping", PING_PONG_MAX_BYTES, 1, PING_PONG_METERING_CONFIGURATION);
  76. /// Inbound keepalive message.
  77. #[derive(Debug, Copy, Clone, SerialEncodable, SerialDecodable)]
  78. pub struct PongMessage {
  79. pub nonce: u16,
  80. }
  81. impl_p2p_message!(PongMessage, "pong", PING_PONG_MAX_BYTES, 1, PING_PONG_METERING_CONFIGURATION);
  82. /// Requests address of outbound connection.
  83. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  84. pub struct GetAddrsMessage {
  85. /// Maximum number of addresses with preferred
  86. /// transports to receive. Response vector will
  87. /// also contain addresses without the preferred
  88. /// transports, so its size will be 2 * max.
  89. pub max: u32,
  90. /// Preferred addresses transports
  91. pub transports: Vec<String>,
  92. }
  93. pub const GET_ADDRS_METERING_CONFIGURATION: MeteringConfiguration = MeteringConfiguration {
  94. threshold: 6,
  95. sleep_step: 1000,
  96. expiry_time: NanoTimestamp::from_secs(10),
  97. };
  98. /// GetAddrs message fields size
  99. /// * max = 4
  100. /// * transports = 1 (vec_len) + 4 + 4 + 4 + 4 + 4 + 8 + 8 + 8 + 8 = 53
  101. ///
  102. /// Transports is list of all transports to be shared specified in protocol_address
  103. pub const GET_ADDRS_MAX_BYTES: u64 = 57;
  104. impl_p2p_message!(
  105. GetAddrsMessage,
  106. "getaddr",
  107. GET_ADDRS_MAX_BYTES,
  108. 1,
  109. GET_ADDRS_METERING_CONFIGURATION
  110. );
  111. /// Sends address information to inbound connection.
  112. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  113. pub struct AddrsMessage {
  114. pub addrs: Vec<(Url, u64)>,
  115. }
  116. pub const ADDRS_METERING_CONFIGURATION: MeteringConfiguration = MeteringConfiguration {
  117. threshold: 6,
  118. sleep_step: 1000,
  119. expiry_time: NanoTimestamp::from_secs(10),
  120. };
  121. /// Addrs message fields size
  122. /// * addrs = 1 (vec_len) + (u8::MAX * 2) * 128
  123. ///
  124. /// Url type is estimated to be max 128 bytes here and for other message below
  125. pub const ADDRS_MAX_BYTES: u64 = 65281;
  126. impl_p2p_message!(AddrsMessage, "addr", ADDRS_MAX_BYTES, 1, ADDRS_METERING_CONFIGURATION);
  127. /// Requests version information of outbound connection.
  128. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  129. pub struct VersionMessage {
  130. /// Only used for debugging. Compromises privacy when set.
  131. pub node_id: String,
  132. /// Identifies protocol version being used by the node
  133. pub version: semver::Version,
  134. /// UNIX timestamp of when the VersionMessage was created.
  135. pub timestamp: u64,
  136. /// Network address of the node receiving this message (before
  137. /// resolving).
  138. pub connect_recv_addr: Url,
  139. /// Network address of the node receiving this message (after
  140. /// resolving). Optional because only used by outbound connections.
  141. pub resolve_recv_addr: Option<Url>,
  142. /// External address of the sender node, if it exists (empty
  143. /// otherwise).
  144. pub ext_send_addr: Vec<Url>,
  145. /// List of features consisting of a tuple of (services, version)
  146. /// to be enabled for this connection
  147. pub features: Vec<(String, u32)>,
  148. }
  149. pub const VERSION_METERING_CONFIGURATION: MeteringConfiguration = MeteringConfiguration {
  150. threshold: 4,
  151. sleep_step: 1000,
  152. expiry_time: NanoTimestamp::from_secs(10),
  153. };
  154. /// Version message fields size
  155. /// * node_id = 8 (this will be empty most of the time)
  156. /// * version = 128 (look at VerackMessage for the reasoning)
  157. /// * timestamp = 8
  158. /// * connect_recv_addr = 128
  159. /// * resolve_recv_addr = 1 (enum_len) + 128(url) = 129
  160. /// * ext_send_addr = 1 (vec_len) + 128 * 10 = 1281 (10 is a reasonable cap for number of external addresses)
  161. /// * features = 1 (vec_len) + (32 (service_name) + 4 (service_version)) * 10 = 361 (10 features is an estimate)
  162. pub const VERSION_MAX_BYTES: u64 = 2043;
  163. impl_p2p_message!(VersionMessage, "version", VERSION_MAX_BYTES, 1, VERSION_METERING_CONFIGURATION);
  164. impl VersionMessage {
  165. pub(in crate::net) fn get_ipv6_addr(&self) -> Option<Ipv6Addr> {
  166. let host = self.connect_recv_addr.host()?;
  167. // Check the reported address is Ipv6
  168. match host {
  169. Host::Ipv6(addr) => Some(addr),
  170. _ => None,
  171. }
  172. }
  173. }
  174. /// Sends version information to inbound connection.
  175. /// Response to `VersionMessage`.
  176. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  177. pub struct VerackMessage {
  178. /// App version
  179. pub app_version: semver::Version,
  180. }
  181. pub const VERACK_METERING_CONFIGURATION: MeteringConfiguration = MeteringConfiguration {
  182. threshold: 4,
  183. sleep_step: 1000,
  184. expiry_time: NanoTimestamp::from_secs(10),
  185. };
  186. /// Verack message fields size
  187. /// * app_version = 24 (major = 8, minor = 8, patch = 8) + 52 (prerelease = 1(str_len) + 51(str)) + 52 (build = 1(str_len) + 51(str))
  188. ///
  189. /// Prerelease and build strings are variable length but shouldn't be larger than 102 bytes
  190. pub const VERACK_MAX_BYTES: u64 = 128;
  191. impl_p2p_message!(VerackMessage, "verack", VERACK_MAX_BYTES, 1, VERACK_METERING_CONFIGURATION);