message.rs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2026 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
  61. /// maximum number of messages in a 10 seconds window and multiply it
  62. /// by 2 not to be strict.
  63. pub const PING_PONG_METERING_CONFIGURATION: MeteringConfiguration = MeteringConfiguration {
  64. threshold: 4,
  65. sleep_step: 1000,
  66. expiry_time: NanoTimestamp::from_secs(10),
  67. };
  68. /// Ping-Pong messages fields size:
  69. /// * nonce = 2
  70. pub const PING_PONG_MAX_BYTES: u64 = 2;
  71. /// Outbound keepalive message.
  72. #[derive(Debug, Copy, Clone, SerialEncodable, SerialDecodable)]
  73. pub struct PingMessage {
  74. pub nonce: u16,
  75. }
  76. impl_p2p_message!(PingMessage, "ping", PING_PONG_MAX_BYTES, 1, PING_PONG_METERING_CONFIGURATION);
  77. /// Inbound keepalive message.
  78. #[derive(Debug, Copy, Clone, SerialEncodable, SerialDecodable)]
  79. pub struct PongMessage {
  80. pub nonce: u16,
  81. }
  82. impl_p2p_message!(PongMessage, "pong", PING_PONG_MAX_BYTES, 1, PING_PONG_METERING_CONFIGURATION);
  83. /// Requests address of outbound connection.
  84. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  85. pub struct GetAddrsMessage {
  86. /// Maximum number of addresses with preferred
  87. /// transports to receive. Response vector will
  88. /// also contain addresses without the preferred
  89. /// transports, so its size will be 2 * max.
  90. pub max: u32,
  91. /// Preferred addresses transports.
  92. pub transports: Vec<String>,
  93. }
  94. pub const GET_ADDRS_METERING_CONFIGURATION: MeteringConfiguration = MeteringConfiguration {
  95. threshold: 6,
  96. sleep_step: 1000,
  97. expiry_time: NanoTimestamp::from_secs(10),
  98. };
  99. /// GetAddrs message fields size:
  100. /// * max = 4
  101. /// * transports = 1 (vec_len) + 4 + 4 + 4 + 4 + 4 + 8 + 8 + 8 + 8 = 53
  102. ///
  103. /// Transports is list of all transports to be shared specified in protocol_address.
  104. pub const GET_ADDRS_MAX_BYTES: u64 = 57;
  105. impl_p2p_message!(
  106. GetAddrsMessage,
  107. "getaddr",
  108. GET_ADDRS_MAX_BYTES,
  109. 1,
  110. GET_ADDRS_METERING_CONFIGURATION
  111. );
  112. /// Sends address information to inbound connection.
  113. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  114. pub struct AddrsMessage {
  115. pub addrs: Vec<(Url, u64)>,
  116. }
  117. pub const ADDRS_METERING_CONFIGURATION: MeteringConfiguration = MeteringConfiguration {
  118. threshold: 6,
  119. sleep_step: 1000,
  120. expiry_time: NanoTimestamp::from_secs(10),
  121. };
  122. /// Addrs message fields size:
  123. /// * addrs = 1 (vec_len) + (u8::MAX * 2) * 128
  124. ///
  125. /// Url type is estimated to be max 128 bytes here and for other message below.
  126. pub const ADDRS_MAX_BYTES: u64 = 65281;
  127. impl_p2p_message!(AddrsMessage, "addr", ADDRS_MAX_BYTES, 1, ADDRS_METERING_CONFIGURATION);
  128. /// Requests version information of outbound connection.
  129. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  130. pub struct VersionMessage {
  131. /// Only used for debugging. Compromises privacy when set.
  132. pub node_id: String,
  133. /// App identifier
  134. pub app_name: String,
  135. /// Identifies protocol version being used by the node.
  136. pub version: semver::Version,
  137. /// UNIX timestamp of when the VersionMessage was created.
  138. pub timestamp: u64,
  139. /// Network address of the node receiving this message (before
  140. /// resolving).
  141. pub connect_recv_addr: Url,
  142. /// Network address of the node receiving this message (after
  143. /// resolving). Optional because only used by outbound connections.
  144. pub resolve_recv_addr: Option<Url>,
  145. /// External address of the sender node, if it exists (empty
  146. /// otherwise).
  147. pub ext_send_addr: Vec<Url>,
  148. /// List of features consisting of a tuple of (services, version)
  149. /// to be enabled for this connection.
  150. pub features: Vec<(String, u32)>,
  151. }
  152. pub const VERSION_METERING_CONFIGURATION: MeteringConfiguration = MeteringConfiguration {
  153. threshold: 4,
  154. sleep_step: 1000,
  155. expiry_time: NanoTimestamp::from_secs(10),
  156. };
  157. /// Version message fields size:
  158. /// * node_id = 8 (this will be empty most of the time)
  159. /// * version = 128 (look at VerackMessage for the reasoning)
  160. /// * timestamp = 8
  161. /// * connect_recv_addr = 128
  162. /// * resolve_recv_addr = 1 (enum_len) + 128(url) = 129
  163. /// * ext_send_addr = 1 (vec_len) + 128 * 10 = 1281 (10 is a reasonable cap for number of external addresses)
  164. /// * features = 1 (vec_len) + (32 (service_name) + 4 (service_version)) * 10 = 361 (10 features is an estimate)
  165. pub const VERSION_MAX_BYTES: u64 = 2043;
  166. impl_p2p_message!(VersionMessage, "version", VERSION_MAX_BYTES, 1, VERSION_METERING_CONFIGURATION);
  167. impl VersionMessage {
  168. pub(in crate::net) fn get_ipv6_addr(&self) -> Option<Ipv6Addr> {
  169. let host = self.connect_recv_addr.host()?;
  170. // Check the reported address is Ipv6
  171. match host {
  172. Host::Ipv6(addr) => Some(addr),
  173. _ => None,
  174. }
  175. }
  176. }
  177. /// Sends version information to inbound connection.
  178. /// Response to `VersionMessage`.
  179. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  180. pub struct VerackMessage {
  181. /// App version
  182. pub app_version: semver::Version,
  183. /// App identifier
  184. pub app_name: String,
  185. }
  186. pub const VERACK_METERING_CONFIGURATION: MeteringConfiguration = MeteringConfiguration {
  187. threshold: 4,
  188. sleep_step: 1000,
  189. expiry_time: NanoTimestamp::from_secs(10),
  190. };
  191. /// Verack message fields size:
  192. /// * app_version = 24 (major = 8, minor = 8, patch = 8) + 52 (prerelease = 1(str_len) + 51(str)) + 52 (build = 1(str_len) + 51(str))
  193. ///
  194. /// Prerelease and build strings are variable length but shouldn't be larger than 102 bytes.
  195. pub const VERACK_MAX_BYTES: u64 = 128;
  196. impl_p2p_message!(VerackMessage, "verack", VERACK_MAX_BYTES, 1, VERACK_METERING_CONFIGURATION);