librats 1.0.2 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (319) hide show
  1. package/README.md +145 -331
  2. package/binding.gyp +16 -3
  3. package/lib/index.d.ts +288 -696
  4. package/lib/index.js +407 -44
  5. package/native-src/3rdparty/android/ifaddrs-android.c +1 -0
  6. package/native-src/3rdparty/android/ifaddrs-android.h +1 -0
  7. package/native-src/CMakeLists.txt +404 -179
  8. package/native-src/LICENSE +1 -1
  9. package/native-src/src/librats/bindings/rats.cpp +762 -0
  10. package/native-src/src/librats/bindings/rats.h +380 -0
  11. package/native-src/src/librats/bittorrent/bencode.cpp +437 -0
  12. package/native-src/src/librats/bittorrent/bencode.h +176 -0
  13. package/native-src/src/librats/bittorrent/bitfield.cpp +97 -0
  14. package/native-src/src/librats/bittorrent/bitfield.h +76 -0
  15. package/native-src/src/librats/bittorrent/byte_io.h +58 -0
  16. package/native-src/src/librats/bittorrent/choker.cpp +25 -0
  17. package/native-src/src/librats/bittorrent/choker.h +46 -0
  18. package/native-src/src/librats/bittorrent/client.cpp +413 -0
  19. package/native-src/src/librats/bittorrent/client.h +227 -0
  20. package/native-src/src/librats/bittorrent/disk_io.cpp +209 -0
  21. package/native-src/src/librats/bittorrent/disk_io.h +150 -0
  22. package/native-src/src/librats/bittorrent/extensions.cpp +191 -0
  23. package/native-src/src/librats/bittorrent/extensions.h +94 -0
  24. package/native-src/src/librats/bittorrent/file_storage.cpp +77 -0
  25. package/native-src/src/librats/bittorrent/file_storage.h +79 -0
  26. package/native-src/src/librats/bittorrent/log.h +42 -0
  27. package/native-src/src/librats/bittorrent/magnet_uri.cpp +98 -0
  28. package/native-src/src/librats/bittorrent/magnet_uri.h +35 -0
  29. package/native-src/src/librats/bittorrent/peer_connection.cpp +502 -0
  30. package/native-src/src/librats/bittorrent/peer_connection.h +194 -0
  31. package/native-src/src/librats/bittorrent/peer_list.cpp +68 -0
  32. package/native-src/src/librats/bittorrent/peer_list.h +75 -0
  33. package/native-src/src/librats/bittorrent/piece_picker.cpp +352 -0
  34. package/native-src/src/librats/bittorrent/piece_picker.h +201 -0
  35. package/native-src/src/librats/bittorrent/reactor.cpp +97 -0
  36. package/native-src/src/librats/bittorrent/reactor.h +89 -0
  37. package/native-src/src/librats/bittorrent/resume_data.cpp +72 -0
  38. package/native-src/src/librats/bittorrent/resume_data.h +41 -0
  39. package/native-src/src/librats/bittorrent/store_buffer.cpp +48 -0
  40. package/native-src/src/librats/bittorrent/store_buffer.h +47 -0
  41. package/native-src/src/librats/bittorrent/torrent.cpp +870 -0
  42. package/native-src/src/librats/bittorrent/torrent.h +260 -0
  43. package/native-src/src/librats/bittorrent/torrent_creator.cpp +129 -0
  44. package/native-src/src/librats/bittorrent/torrent_creator.h +58 -0
  45. package/native-src/src/librats/bittorrent/torrent_info.cpp +314 -0
  46. package/native-src/src/librats/bittorrent/torrent_info.h +118 -0
  47. package/native-src/src/librats/bittorrent/tracker.cpp +374 -0
  48. package/native-src/src/librats/bittorrent/tracker.h +108 -0
  49. package/native-src/src/librats/bittorrent/types.cpp +206 -0
  50. package/native-src/src/librats/bittorrent/types.h +86 -0
  51. package/native-src/src/librats/core/address.cpp +35 -0
  52. package/native-src/src/librats/core/address.h +78 -0
  53. package/native-src/src/librats/core/bytes.h +69 -0
  54. package/native-src/src/librats/core/chained_send_buffer.cpp +172 -0
  55. package/native-src/src/librats/core/chained_send_buffer.h +183 -0
  56. package/native-src/src/librats/core/endpoint_parse.cpp +41 -0
  57. package/native-src/src/librats/core/endpoint_parse.h +31 -0
  58. package/native-src/src/librats/core/event_bus.h +70 -0
  59. package/native-src/src/librats/core/host_endpoint.h +56 -0
  60. package/native-src/src/{io_poller.cpp → librats/core/io_poller.cpp} +520 -65
  61. package/native-src/src/{io_poller.h → librats/core/io_poller.h} +12 -6
  62. package/native-src/src/librats/core/ip_address.cpp +120 -0
  63. package/native-src/src/librats/core/ip_address.h +109 -0
  64. package/native-src/src/librats/core/mpsc_queue.h +47 -0
  65. package/native-src/src/librats/core/notifier.h +74 -0
  66. package/native-src/src/librats/core/receive_buffer.cpp +219 -0
  67. package/native-src/src/librats/core/receive_buffer.h +171 -0
  68. package/native-src/src/librats/core/service_registry.h +58 -0
  69. package/native-src/src/{socket.cpp → librats/core/socket.cpp} +625 -118
  70. package/native-src/src/librats/core/socket.h +496 -0
  71. package/native-src/src/librats/core/timer_queue.h +105 -0
  72. package/native-src/src/librats/core/types.cpp +43 -0
  73. package/native-src/src/librats/core/types.h +103 -0
  74. package/native-src/src/librats/core/wakeup_pipe.h +83 -0
  75. package/native-src/src/{crypto → librats/crypto}/blake2_endian.h +21 -23
  76. package/native-src/src/{crypto → librats/crypto}/blake2b.c +34 -33
  77. package/native-src/src/{crypto → librats/crypto}/blake2b.h +7 -6
  78. package/native-src/src/{crypto → librats/crypto}/blake2s.c +55 -54
  79. package/native-src/src/{crypto → librats/crypto}/blake2s.h +13 -12
  80. package/native-src/src/{crypto → librats/crypto}/chacha.c +22 -21
  81. package/native-src/src/{crypto → librats/crypto}/chacha.h +14 -13
  82. package/native-src/src/{crypto → librats/crypto}/chachapoly.c +56 -56
  83. package/native-src/src/{crypto → librats/crypto}/chachapoly.h +24 -17
  84. package/native-src/src/{crc32.cpp → librats/crypto/crc32.cpp} +1 -1
  85. package/native-src/src/{crc32.h → librats/crypto/crc32.h} +3 -1
  86. package/native-src/src/{crypto → librats/crypto}/curve25519.c +6 -4
  87. package/native-src/src/{crypto → librats/crypto}/curve25519.h +6 -3
  88. package/native-src/src/librats/crypto/hkdf.c +266 -0
  89. package/native-src/src/{crypto → librats/crypto}/hkdf.h +19 -19
  90. package/native-src/src/{noise.cpp → librats/crypto/noise.cpp} +84 -73
  91. package/native-src/src/{noise.h → librats/crypto/noise.h} +18 -8
  92. package/native-src/src/{crypto → librats/crypto}/poly1305.c +47 -46
  93. package/native-src/src/librats/crypto/poly1305.h +37 -0
  94. package/native-src/src/{sha1.cpp → librats/crypto/sha1.cpp} +33 -1
  95. package/native-src/src/{sha1.h → librats/crypto/sha1.h} +14 -6
  96. package/native-src/src/{crypto → librats/crypto}/sha256.c +15 -14
  97. package/native-src/src/{crypto → librats/crypto}/sha256.h +8 -7
  98. package/native-src/src/{crypto → librats/crypto}/sha512.c +15 -14
  99. package/native-src/src/{crypto → librats/crypto}/sha512.h +8 -7
  100. package/native-src/src/librats/dht/announce.cpp +37 -0
  101. package/native-src/src/librats/dht/announce.h +41 -0
  102. package/native-src/src/librats/dht/bep42.cpp +109 -0
  103. package/native-src/src/librats/dht/bep42.h +48 -0
  104. package/native-src/src/librats/dht/dht.cpp +501 -0
  105. package/native-src/src/librats/dht/dht.h +119 -0
  106. package/native-src/src/librats/dht/dht_runner.cpp +103 -0
  107. package/native-src/src/librats/dht/dht_runner.h +71 -0
  108. package/native-src/src/librats/dht/dos_blocker.cpp +42 -0
  109. package/native-src/src/librats/dht/dos_blocker.h +47 -0
  110. package/native-src/src/librats/dht/find_peers.cpp +52 -0
  111. package/native-src/src/librats/dht/find_peers.h +73 -0
  112. package/native-src/src/librats/dht/id.h +167 -0
  113. package/native-src/src/{krpc.cpp → librats/dht/krpc.cpp} +32 -81
  114. package/native-src/src/{krpc.h → librats/dht/krpc.h} +19 -23
  115. package/native-src/src/librats/dht/log.h +38 -0
  116. package/native-src/src/librats/dht/node.cpp +473 -0
  117. package/native-src/src/librats/dht/node.h +164 -0
  118. package/native-src/src/librats/dht/node_entry.h +81 -0
  119. package/native-src/src/librats/dht/observer.h +72 -0
  120. package/native-src/src/librats/dht/persistence.cpp +90 -0
  121. package/native-src/src/librats/dht/persistence.h +32 -0
  122. package/native-src/src/librats/dht/routing_table.cpp +559 -0
  123. package/native-src/src/librats/dht/routing_table.h +185 -0
  124. package/native-src/src/librats/dht/rpc_manager.cpp +127 -0
  125. package/native-src/src/librats/dht/rpc_manager.h +77 -0
  126. package/native-src/src/librats/dht/storage.cpp +92 -0
  127. package/native-src/src/librats/dht/storage.h +74 -0
  128. package/native-src/src/librats/dht/transport.h +27 -0
  129. package/native-src/src/librats/dht/traversal.cpp +326 -0
  130. package/native-src/src/librats/dht/traversal.h +120 -0
  131. package/native-src/src/librats/dht/udp_transport.cpp +49 -0
  132. package/native-src/src/librats/dht/udp_transport.h +51 -0
  133. package/native-src/src/librats/mdns/log.h +22 -0
  134. package/native-src/src/{mdns.cpp → librats/mdns/mdns.cpp} +75 -40
  135. package/native-src/src/{mdns.h → librats/mdns/mdns.h} +9 -8
  136. package/native-src/src/{natpmp.cpp → librats/nat/natpmp.cpp} +12 -9
  137. package/native-src/src/{natpmp.h → librats/nat/natpmp.h} +3 -3
  138. package/native-src/src/{port_mapping.h → librats/nat/port_mapping.h} +3 -2
  139. package/native-src/src/{stun.cpp → librats/nat/stun.cpp} +4 -4
  140. package/native-src/src/{stun.h → librats/nat/stun.h} +1 -1
  141. package/native-src/src/{upnp.cpp → librats/nat/upnp.cpp} +6 -6
  142. package/native-src/src/{upnp.h → librats/nat/upnp.h} +2 -2
  143. package/native-src/src/librats/node/circuit_service.h +84 -0
  144. package/native-src/src/librats/node/config.h +110 -0
  145. package/native-src/src/librats/node/dial_service.h +54 -0
  146. package/native-src/src/librats/node/dialer.cpp +264 -0
  147. package/native-src/src/librats/node/dialer.h +188 -0
  148. package/native-src/src/librats/node/host_events.h +26 -0
  149. package/native-src/src/librats/node/identify.cpp +130 -0
  150. package/native-src/src/librats/node/identify.h +71 -0
  151. package/native-src/src/librats/node/nat_status.cpp +103 -0
  152. package/native-src/src/librats/node/nat_status.h +118 -0
  153. package/native-src/src/librats/node/node.cpp +865 -0
  154. package/native-src/src/librats/node/node.h +344 -0
  155. package/native-src/src/librats/node/node_context.h +33 -0
  156. package/native-src/src/librats/node/peer_network.h +91 -0
  157. package/native-src/src/librats/peer/peer.h +49 -0
  158. package/native-src/src/librats/peer/peer_book.cpp +181 -0
  159. package/native-src/src/librats/peer/peer_book.h +88 -0
  160. package/native-src/src/librats/peer/peer_id.cpp +72 -0
  161. package/native-src/src/librats/peer/peer_id.h +62 -0
  162. package/native-src/src/librats/peer/peer_info.h +37 -0
  163. package/native-src/src/librats/peer/peer_table.cpp +170 -0
  164. package/native-src/src/librats/peer/peer_table.h +148 -0
  165. package/native-src/src/librats/security/handshaker.h +66 -0
  166. package/native-src/src/librats/security/identity.h +43 -0
  167. package/native-src/src/librats/security/noise_security.cpp +122 -0
  168. package/native-src/src/librats/security/noise_security.h +37 -0
  169. package/native-src/src/librats/security/plaintext_security.h +106 -0
  170. package/native-src/src/librats/security/session.h +37 -0
  171. package/native-src/src/{storage.cpp → librats/storage/storage.cpp} +369 -522
  172. package/native-src/src/{storage.h → librats/storage/storage.h} +135 -299
  173. package/native-src/src/librats/subsystems/bittorrent.cpp +211 -0
  174. package/native-src/src/librats/subsystems/bittorrent.h +136 -0
  175. package/native-src/src/librats/subsystems/dht_discovery.cpp +202 -0
  176. package/native-src/src/librats/subsystems/dht_discovery.h +123 -0
  177. package/native-src/src/librats/subsystems/dht_service.h +36 -0
  178. package/native-src/src/librats/subsystems/file_transfer.cpp +972 -0
  179. package/native-src/src/librats/subsystems/file_transfer.h +367 -0
  180. package/native-src/src/librats/subsystems/hole_punch.cpp +605 -0
  181. package/native-src/src/librats/subsystems/hole_punch.h +290 -0
  182. package/native-src/src/librats/subsystems/hole_punch_service.h +38 -0
  183. package/native-src/src/librats/subsystems/mdns_discovery.cpp +66 -0
  184. package/native-src/src/librats/subsystems/mdns_discovery.h +55 -0
  185. package/native-src/src/librats/subsystems/message_json.cpp +112 -0
  186. package/native-src/src/librats/subsystems/message_json.h +88 -0
  187. package/native-src/src/librats/subsystems/peer_exchange.cpp +241 -0
  188. package/native-src/src/librats/subsystems/peer_exchange.h +136 -0
  189. package/native-src/src/librats/subsystems/ping_service.cpp +98 -0
  190. package/native-src/src/librats/subsystems/ping_service.h +66 -0
  191. package/native-src/src/librats/subsystems/port_mapping_service.cpp +192 -0
  192. package/native-src/src/librats/subsystems/port_mapping_service.h +84 -0
  193. package/native-src/src/librats/subsystems/pubsub.cpp +567 -0
  194. package/native-src/src/librats/subsystems/pubsub.h +175 -0
  195. package/native-src/src/librats/subsystems/reconnection.cpp +239 -0
  196. package/native-src/src/librats/subsystems/reconnection.h +126 -0
  197. package/native-src/src/librats/subsystems/relay.cpp +1142 -0
  198. package/native-src/src/librats/subsystems/relay.h +211 -0
  199. package/native-src/src/librats/subsystems/relay_service.h +46 -0
  200. package/native-src/src/librats/transport/connection.cpp +343 -0
  201. package/native-src/src/librats/transport/connection.h +283 -0
  202. package/native-src/src/librats/transport/link.h +96 -0
  203. package/native-src/src/librats/transport/reactor.cpp +588 -0
  204. package/native-src/src/librats/transport/reactor.h +262 -0
  205. package/native-src/src/librats/transport/reactor_pool.h +81 -0
  206. package/native-src/src/librats/transport/relay_link.cpp +208 -0
  207. package/native-src/src/librats/transport/relay_link.h +303 -0
  208. package/native-src/src/librats/transport/tcp_link.cpp +49 -0
  209. package/native-src/src/librats/transport/tcp_link.h +43 -0
  210. package/native-src/src/librats/transport/udp_mux.cpp +617 -0
  211. package/native-src/src/librats/transport/udp_mux.h +363 -0
  212. package/native-src/src/librats/transport/udp_packet.cpp +121 -0
  213. package/native-src/src/librats/transport/udp_packet.h +190 -0
  214. package/native-src/src/librats/transport/udp_stream.cpp +1194 -0
  215. package/native-src/src/librats/transport/udp_stream.h +614 -0
  216. package/native-src/src/librats/util/features.h.in +51 -0
  217. package/native-src/src/{fs.cpp → librats/util/fs.cpp} +51 -3
  218. package/native-src/src/librats/util/fs.h +136 -0
  219. package/native-src/src/librats/util/json.cpp +1002 -0
  220. package/native-src/src/librats/util/json.h +444 -0
  221. package/native-src/src/{logger.cpp → librats/util/logger.cpp} +1 -1
  222. package/native-src/src/{logger.h → librats/util/logger.h} +43 -31
  223. package/native-src/src/{network_monitor.cpp → librats/util/network_monitor.cpp} +12 -4
  224. package/native-src/src/{network_monitor.h → librats/util/network_monitor.h} +2 -1
  225. package/native-src/src/{network_utils.cpp → librats/util/network_utils.cpp} +38 -23
  226. package/native-src/src/{network_utils.h → librats/util/network_utils.h} +15 -8
  227. package/native-src/src/{os.cpp → librats/util/os.cpp} +48 -18
  228. package/native-src/src/librats/util/rats_export.h +69 -0
  229. package/native-src/src/{version.cpp → librats/util/version.cpp} +2 -2
  230. package/native-src/src/{version.h.in → librats/util/version.h.in} +1 -1
  231. package/native-src/src/librats/wire/frame.cpp +76 -0
  232. package/native-src/src/librats/wire/frame.h +111 -0
  233. package/native-src/src/librats/wire/message_router.cpp +45 -0
  234. package/native-src/src/librats/wire/message_router.h +47 -0
  235. package/package.json +5 -4
  236. package/scripts/build-librats.js +1 -0
  237. package/scripts/postinstall.js +3 -3
  238. package/scripts/prepare-package.js +4 -4
  239. package/scripts/verify-installation.js +63 -105
  240. package/src/librats_node.cpp +1067 -1323
  241. package/native-src/src/bencode.cpp +0 -485
  242. package/native-src/src/bencode.h +0 -145
  243. package/native-src/src/bittorrent.cpp +0 -14
  244. package/native-src/src/bittorrent.h +0 -74
  245. package/native-src/src/bt_bitfield.cpp +0 -372
  246. package/native-src/src/bt_bitfield.h +0 -316
  247. package/native-src/src/bt_choker.cpp +0 -228
  248. package/native-src/src/bt_choker.h +0 -147
  249. package/native-src/src/bt_client.cpp +0 -1047
  250. package/native-src/src/bt_client.h +0 -445
  251. package/native-src/src/bt_create_torrent.cpp +0 -677
  252. package/native-src/src/bt_create_torrent.h +0 -473
  253. package/native-src/src/bt_extension.cpp +0 -469
  254. package/native-src/src/bt_extension.h +0 -309
  255. package/native-src/src/bt_file_storage.cpp +0 -261
  256. package/native-src/src/bt_file_storage.h +0 -298
  257. package/native-src/src/bt_handshake.cpp +0 -134
  258. package/native-src/src/bt_handshake.h +0 -157
  259. package/native-src/src/bt_messages.cpp +0 -364
  260. package/native-src/src/bt_messages.h +0 -324
  261. package/native-src/src/bt_network.cpp +0 -1007
  262. package/native-src/src/bt_network.h +0 -417
  263. package/native-src/src/bt_peer_connection.cpp +0 -742
  264. package/native-src/src/bt_peer_connection.h +0 -592
  265. package/native-src/src/bt_piece_picker.cpp +0 -786
  266. package/native-src/src/bt_piece_picker.h +0 -473
  267. package/native-src/src/bt_resume_data.cpp +0 -410
  268. package/native-src/src/bt_resume_data.h +0 -249
  269. package/native-src/src/bt_torrent.cpp +0 -2120
  270. package/native-src/src/bt_torrent.h +0 -641
  271. package/native-src/src/bt_torrent_info.cpp +0 -659
  272. package/native-src/src/bt_torrent_info.h +0 -418
  273. package/native-src/src/bt_types.h +0 -621
  274. package/native-src/src/chained_send_buffer.cpp +0 -75
  275. package/native-src/src/chained_send_buffer.h +0 -137
  276. package/native-src/src/crypto/hkdf.c +0 -266
  277. package/native-src/src/crypto/poly1305.h +0 -36
  278. package/native-src/src/dht.cpp +0 -3311
  279. package/native-src/src/dht.h +0 -717
  280. package/native-src/src/disk_io.cpp +0 -632
  281. package/native-src/src/disk_io.h +0 -315
  282. package/native-src/src/file_transfer.cpp +0 -1415
  283. package/native-src/src/file_transfer.h +0 -286
  284. package/native-src/src/fs.h +0 -108
  285. package/native-src/src/gossipsub.cpp +0 -1139
  286. package/native-src/src/gossipsub.h +0 -403
  287. package/native-src/src/ice.cpp +0 -893
  288. package/native-src/src/ice.h +0 -559
  289. package/native-src/src/json.hpp +0 -25526
  290. package/native-src/src/librats.cpp +0 -2378
  291. package/native-src/src/librats.h +0 -2324
  292. package/native-src/src/librats_bittorrent.cpp +0 -601
  293. package/native-src/src/librats_c.cpp +0 -1557
  294. package/native-src/src/librats_c.h +0 -323
  295. package/native-src/src/librats_discovery.cpp +0 -402
  296. package/native-src/src/librats_encryption.cpp +0 -275
  297. package/native-src/src/librats_file_transfer.cpp +0 -144
  298. package/native-src/src/librats_gossipsub.cpp +0 -289
  299. package/native-src/src/librats_ice.cpp +0 -213
  300. package/native-src/src/librats_log_macros.h +0 -36
  301. package/native-src/src/librats_logging.cpp +0 -173
  302. package/native-src/src/librats_mdns.cpp +0 -166
  303. package/native-src/src/librats_persistence.cpp +0 -796
  304. package/native-src/src/librats_portmap.cpp +0 -419
  305. package/native-src/src/librats_reconnection.cpp +0 -218
  306. package/native-src/src/librats_statistic.cpp +0 -105
  307. package/native-src/src/librats_storage.cpp +0 -189
  308. package/native-src/src/rats_export.h +0 -17
  309. package/native-src/src/receive_buffer.cpp +0 -82
  310. package/native-src/src/receive_buffer.h +0 -127
  311. package/native-src/src/socket.h +0 -228
  312. package/native-src/src/threadmanager.cpp +0 -105
  313. package/native-src/src/threadmanager.h +0 -53
  314. package/native-src/src/tracker.cpp +0 -1264
  315. package/native-src/src/tracker.h +0 -319
  316. package/native-src/src/turn.cpp +0 -762
  317. package/native-src/src/turn.h +0 -460
  318. package/native-src/src/wakeup_pipe.h +0 -60
  319. /package/native-src/src/{os.h → librats/util/os.h} +0 -0
@@ -1,7 +1,8 @@
1
- #include "mdns.h"
2
- #include "network_utils.h"
3
- #include "os.h"
4
- #include "socket.h"
1
+ #include "librats/mdns/mdns.h"
2
+ #include "librats/mdns/log.h"
3
+ #include "librats/util/network_utils.h"
4
+ #include "librats/util/os.h"
5
+ #include "librats/core/socket.h"
5
6
  #include <algorithm>
6
7
  #include <random>
7
8
  #include <sstream>
@@ -26,7 +27,7 @@ MdnsClient::MdnsClient(const std::string& service_instance_name, uint16_t servic
26
27
  : service_instance_name_(service_instance_name),
27
28
  service_port_(service_port),
28
29
  service_type_(LIBRATS_SERVICE_TYPE), // Default service type
29
- multicast_socket_(INVALID_SOCKET_VALUE),
30
+ multicast_socket_(RATS_INVALID_SOCKET),
30
31
  running_(false),
31
32
  announcing_(false),
32
33
  discovering_(false),
@@ -90,11 +91,11 @@ void MdnsClient::stop() {
90
91
 
91
92
  // Trigger immediate shutdown of all background threads
92
93
  shutdown_immediate();
93
-
94
- // Close socket to break receiver loop
95
- close_multicast_socket();
96
-
97
- // Wait for threads to finish
94
+
95
+ // Wait for threads to finish. They must be gone before the socket is closed:
96
+ // the receiver is waiting on it, so closing it first would race with that wait.
97
+ // shutdown_immediate() has already signalled the wakeup pipe, so the wait is
98
+ // over as soon as the scheduler gets to it rather than at the next timeout.
98
99
  if (receiver_thread_.joinable()) {
99
100
  receiver_thread_.join();
100
101
  }
@@ -106,6 +107,9 @@ void MdnsClient::stop() {
106
107
  if (querier_thread_.joinable()) {
107
108
  querier_thread_.join();
108
109
  }
110
+
111
+ // Now that nothing else touches it, close the socket
112
+ close_multicast_socket();
109
113
 
110
114
  // Clear discovered services
111
115
  {
@@ -124,8 +128,11 @@ void MdnsClient::shutdown_immediate() {
124
128
  discovering_.store(false);
125
129
  running_.store(false);
126
130
 
127
- // Notify all waiting threads to wake up immediately
131
+ // Notify all waiting threads to wake up immediately. The announcer and querier
132
+ // sleep on the condition variable; the receiver is parked in a select() on the
133
+ // multicast socket and only the wakeup pipe can break that.
128
134
  shutdown_cv_.notify_all();
135
+ receiver_wakeup_.signal();
129
136
  }
130
137
 
131
138
  bool MdnsClient::is_running() const {
@@ -324,7 +331,7 @@ bool MdnsClient::create_multicast_socket() {
324
331
  LOG_MDNS_ERROR("Failed to bind to mDNS port " << MDNS_PORT << " (error: " << strerror(errno) << ")");
325
332
  #endif
326
333
  close_socket(multicast_socket_);
327
- multicast_socket_ = INVALID_SOCKET_VALUE;
334
+ multicast_socket_ = RATS_INVALID_SOCKET;
328
335
  return false;
329
336
  }
330
337
 
@@ -419,46 +426,74 @@ void MdnsClient::close_multicast_socket() {
419
426
  if (librats::is_valid_socket(multicast_socket_)) {
420
427
  leave_multicast_group();
421
428
  librats::close_socket(multicast_socket_, true);
422
- multicast_socket_ = INVALID_SOCKET_VALUE;
429
+ multicast_socket_ = RATS_INVALID_SOCKET;
423
430
  }
424
431
  }
425
432
 
426
433
  void MdnsClient::receiver_loop() {
427
434
  LOG_MDNS_DEBUG("mDNS receiver loop started");
428
-
429
- std::vector<uint8_t> buffer(4096);
430
- sockaddr_in sender_addr{};
431
- socklen_t addr_len = sizeof(sender_addr);
432
-
435
+
436
+ // stop() must be able to wind this loop down and join it *before* the socket is
437
+ // closed — closing an fd out from under a blocked recvfrom() races with it, since
438
+ // the number can be handed to another thread's socket()/open() the moment it is
439
+ // freed. The wakeup pipe is what makes that possible without polling: the wait
440
+ // watches it alongside the multicast socket, and shutdown_immediate() signals it.
441
+ //
442
+ // Waiting on a timeout instead would cost a wakeup per interval for the entire
443
+ // life of the process. On an idle node that is the *only* work being done, and it
444
+ // is paid per MdnsClient — measured at ~0.1 % of a core each with a 100 ms poll.
445
+ const socket_t interrupt_fd = receiver_wakeup_.fd();
446
+
447
+ // Only if the pipe could not be created: then there is nothing to interrupt the
448
+ // wait, so fall back to polling rather than to a blocking receive that stop()
449
+ // could not get out of.
450
+ constexpr int kFallbackTimeoutMs = 100;
451
+ const int receive_timeout_ms = is_valid_socket(interrupt_fd) ? -1 : kFallbackTimeoutMs;
452
+
453
+ // A single failed receive is not fatal (a signal, a transient ICMP error), but a
454
+ // socket that is genuinely dead fails instantly every time — without a bound the
455
+ // loop below degenerates into a busy spin that never ends. Give up after a short
456
+ // run of back-to-back failures; the old blocking loop bailed on the first one.
457
+ constexpr int kMaxConsecutiveErrors = 10;
458
+ int consecutive_errors = 0;
459
+
433
460
  while (running_.load()) {
434
- if (!librats::is_valid_socket(multicast_socket_)) {
435
- break;
436
- }
437
-
438
- int received = recvfrom(multicast_socket_, reinterpret_cast<char*>(buffer.data()),
439
- static_cast<int>(buffer.size()), 0, reinterpret_cast<sockaddr*>(&sender_addr), &addr_len);
440
-
441
- if (received <= 0) {
442
- if (running_.load()) {
443
- LOG_MDNS_ERROR("Failed to receive multicast packet");
461
+ Address sender;
462
+ bool receive_failed = false;
463
+ std::vector<uint8_t> packet = librats::receive_udp_data(
464
+ multicast_socket_, 4096, sender, receive_timeout_ms, interrupt_fd, &receive_failed);
465
+
466
+ if (receive_failed) {
467
+ if (++consecutive_errors >= kMaxConsecutiveErrors) {
468
+ if (running_.load()) {
469
+ LOG_MDNS_ERROR("mDNS receive failed " << consecutive_errors
470
+ << " times in a row, stopping receiver loop");
471
+ }
472
+ break;
444
473
  }
445
- break;
474
+ continue;
446
475
  }
447
-
448
- // Get sender IP address
449
- char sender_ip[INET_ADDRSTRLEN];
450
- inet_ntop(AF_INET, &sender_addr.sin_addr, sender_ip, INET_ADDRSTRLEN);
451
-
476
+
477
+ consecutive_errors = 0;
478
+
479
+ if (packet.empty()) {
480
+ // Either the wait was interrupted or (in the degraded fallback) it timed
481
+ // out. Consume the wakeup byte — an unread one keeps the pipe readable and
482
+ // would turn the next wait into a spin — then re-check running_.
483
+ receiver_wakeup_.drain();
484
+ continue;
485
+ }
486
+
487
+ std::string sender_ip = sender.ip.to_string();
488
+
452
489
  // Ignore packets from ourselves
453
- if (std::string(sender_ip) == local_ip_address_) {
490
+ if (sender_ip == local_ip_address_) {
454
491
  continue;
455
492
  }
456
-
457
- // Process the received packet
458
- std::vector<uint8_t> packet(buffer.begin(), buffer.begin() + received);
459
- handle_received_packet(packet, std::string(sender_ip));
493
+
494
+ handle_received_packet(packet, sender_ip);
460
495
  }
461
-
496
+
462
497
  LOG_MDNS_DEBUG("mDNS receiver loop ended");
463
498
  }
464
499
 
@@ -1,7 +1,7 @@
1
1
  #pragma once
2
2
 
3
- #include "socket.h"
4
- #include "logger.h"
3
+ #include "librats/core/socket.h"
4
+ #include "librats/core/wakeup_pipe.h"
5
5
  #include <string>
6
6
  #include <vector>
7
7
  #include <memory>
@@ -17,11 +17,6 @@
17
17
 
18
18
  namespace librats {
19
19
 
20
- #define LOG_MDNS_DEBUG(message) LOG_DEBUG("mdns", message)
21
- #define LOG_MDNS_INFO(message) LOG_INFO("mdns", message)
22
- #define LOG_MDNS_WARN(message) LOG_WARN("mdns", message)
23
- #define LOG_MDNS_ERROR(message) LOG_ERROR("mdns", message)
24
-
25
20
  // mDNS protocol constants
26
21
  const uint16_t MDNS_PORT = 5353;
27
22
  const std::string MDNS_MULTICAST_IPv4 = "224.0.0.251";
@@ -176,7 +171,13 @@ private:
176
171
  std::thread receiver_thread_;
177
172
  std::thread announcer_thread_;
178
173
  std::thread querier_thread_;
179
-
174
+
175
+ /// Lets stop() interrupt the receiver's blocking wait. Without it the loop
176
+ /// would have to poll the multicast socket on a timeout just to notice that
177
+ /// running_ went false, which costs a wakeup per interval forever — on a
178
+ /// client that is otherwise completely idle, that is the only work it does.
179
+ WakeupPipe receiver_wakeup_;
180
+
180
181
  // Conditional variables for immediate shutdown
181
182
  std::condition_variable shutdown_cv_;
182
183
  std::mutex shutdown_mutex_;
@@ -3,9 +3,9 @@
3
3
  * @brief NAT-PMP (RFC 6886) client implementation
4
4
  */
5
5
 
6
- #include "natpmp.h"
7
- #include "network_utils.h"
8
- #include "logger.h"
6
+ #include "librats/nat/natpmp.h"
7
+ #include "librats/util/network_utils.h"
8
+ #include "librats/util/logger.h"
9
9
 
10
10
  #include <cstring>
11
11
 
@@ -174,14 +174,15 @@ bool NatPmpClient::ensure_gateway() {
174
174
  socket_t sock = create_udp_socket(0, "", AddressFamily::IPv4);
175
175
  if (!is_valid_socket(sock)) continue;
176
176
 
177
+ const auto gw_ip = IpAddress::parse(gw); // gateway is a numeric literal; parse once, compare by bytes
177
178
  std::vector<uint8_t> req = { NATPMP_VERSION, OP_EXTERNAL_IP };
178
179
  bool answered = false;
179
180
  for (int timeout : kRetryTimeouts) {
180
181
  if (stop_requested_.load()) { close_socket(sock); return false; }
181
182
  if (send_udp_data(sock, req, gw, NATPMP_PORT, AddressFamily::IPv4) < 0) break;
182
- Peer from;
183
+ Address from;
183
184
  auto resp = receive_udp_data(sock, 64, from, timeout, wakeup_.fd());
184
- if (resp.size() >= 12 && from.ip == gw && resp[0] == NATPMP_VERSION &&
185
+ if (resp.size() >= 12 && gw_ip && from.ip == *gw_ip && resp[0] == NATPMP_VERSION &&
185
186
  resp[1] == (OP_EXTERNAL_IP | OP_RESPONSE_BIT)) {
186
187
  uint16_t result = get_u16(&resp[2]);
187
188
  if (result == 0) {
@@ -224,14 +225,15 @@ bool NatPmpClient::request_external_ip(socket_t sock) {
224
225
  gw = gateway_;
225
226
  }
226
227
  if (gw.empty()) return false;
228
+ const auto gw_ip = IpAddress::parse(gw); // numeric literal; parse once, compare by bytes
227
229
 
228
230
  std::vector<uint8_t> req = { NATPMP_VERSION, OP_EXTERNAL_IP };
229
231
  for (int timeout : kRetryTimeouts) {
230
232
  if (stop_requested_.load()) return false;
231
233
  if (send_udp_data(sock, req, gw, NATPMP_PORT, AddressFamily::IPv4) < 0) return false;
232
- Peer from;
234
+ Address from;
233
235
  auto resp = receive_udp_data(sock, 64, from, timeout, wakeup_.fd());
234
- if (resp.size() >= 12 && from.ip == gw && resp[0] == NATPMP_VERSION &&
236
+ if (resp.size() >= 12 && gw_ip && from.ip == *gw_ip && resp[0] == NATPMP_VERSION &&
235
237
  resp[1] == (OP_EXTERNAL_IP | OP_RESPONSE_BIT) && get_u16(&resp[2]) == 0) {
236
238
  char ip[INET_ADDRSTRLEN];
237
239
  struct in_addr addr;
@@ -253,6 +255,7 @@ bool NatPmpClient::send_map_request(socket_t sock, Mapping& m, bool remove) {
253
255
  gw = gateway_;
254
256
  }
255
257
  if (gw.empty()) return false;
258
+ const auto gw_ip = IpAddress::parse(gw); // numeric literal; parse once, compare by bytes
256
259
 
257
260
  const uint32_t lifetime = remove ? 0 : lease_duration_;
258
261
  const uint16_t requested_external = remove ? 0 : m.external_port;
@@ -291,9 +294,9 @@ bool NatPmpClient::send_map_request(socket_t sock, Mapping& m, bool remove) {
291
294
  if (stop_requested_.load()) return false;
292
295
  if (send_udp_data(sock, req, gw, NATPMP_PORT, AddressFamily::IPv4) < 0) return false;
293
296
 
294
- Peer from;
297
+ Address from;
295
298
  auto resp = receive_udp_data(sock, 64, from, timeout, wakeup_.fd());
296
- if (resp.size() < 16 || from.ip != gw) continue;
299
+ if (resp.size() < 16 || !gw_ip || from.ip != *gw_ip) continue;
297
300
  if (resp[0] != NATPMP_VERSION || resp[1] != expected_opcode) continue;
298
301
 
299
302
  uint16_t result = get_u16(&resp[2]);
@@ -24,9 +24,9 @@
24
24
  * @endcode
25
25
  */
26
26
 
27
- #include "port_mapping.h"
28
- #include "socket.h"
29
- #include "wakeup_pipe.h"
27
+ #include "librats/nat/port_mapping.h"
28
+ #include "librats/core/socket.h"
29
+ #include "librats/core/wakeup_pipe.h"
30
30
 
31
31
  #include <atomic>
32
32
  #include <condition_variable>
@@ -8,7 +8,8 @@
8
8
  * home router to forward an external (WAN) port to a local (LAN) port so that
9
9
  * inbound peer connections can reach a host behind NAT. They share the small set
10
10
  * of vocabulary types defined here: the transport protocol of the mapping, which
11
- * backend produced a result, and the result/callback shape RatsClient consumes.
11
+ * backend produced a result, and the result/callback shape PortMappingService
12
+ * consumes.
12
13
  */
13
14
 
14
15
  #include <cstdint>
@@ -63,7 +64,7 @@ struct PortMapResult {
63
64
  using PortMapCallback = std::function<void(const PortMapResult&)>;
64
65
 
65
66
  /**
66
- * Configuration for RatsClient's automatic port forwarding.
67
+ * Configuration for automatic port forwarding (see PortMappingService).
67
68
  *
68
69
  * Both backends run in parallel by default; whichever the router supports
69
70
  * succeeds. Disabling one (or all) of them is a matter of flipping a flag.
@@ -5,9 +5,9 @@
5
5
  * Implements RFC 5389 - STUN protocol for NAT traversal.
6
6
  */
7
7
 
8
- #include "stun.h"
9
- #include "logger.h"
10
- #include "network_utils.h"
8
+ #include "librats/nat/stun.h"
9
+ #include "librats/util/logger.h"
10
+ #include "librats/util/network_utils.h"
11
11
  #include <cstring>
12
12
  #include <algorithm>
13
13
  #include <chrono>
@@ -1057,7 +1057,7 @@ std::optional<StunMessage> StunClient::send_request(socket_t socket,
1057
1057
 
1058
1058
  // Wait for response with current RTO
1059
1059
  int wait_time = (std::min)(rto, timeout_ms - total_time);
1060
- Peer sender;
1060
+ Address sender;
1061
1061
 
1062
1062
  auto response_data = receive_udp_data(socket, STUN_MAX_MESSAGE_SIZE, sender, wait_time);
1063
1063
 
@@ -8,7 +8,7 @@
8
8
  * Provides functionality to discover public IP address and port mappings.
9
9
  */
10
10
 
11
- #include "socket.h"
11
+ #include "librats/core/socket.h"
12
12
  #include <array>
13
13
  #include <vector>
14
14
  #include <string>
@@ -3,9 +3,9 @@
3
3
  * @brief UPnP IGD port mapping client implementation
4
4
  */
5
5
 
6
- #include "upnp.h"
7
- #include "socket.h"
8
- #include "logger.h"
6
+ #include "librats/nat/upnp.h"
7
+ #include "librats/core/socket.h"
8
+ #include "librats/util/logger.h"
9
9
 
10
10
  #include <cstring>
11
11
  #include <cstdio>
@@ -313,7 +313,7 @@ bool UpnpClient::discover_device(Device& out) {
313
313
 
314
314
  auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(2);
315
315
  while (std::chrono::steady_clock::now() < deadline && !stop_requested_.load()) {
316
- Peer from;
316
+ Address from;
317
317
  auto resp = receive_udp_data(sock, 2048, from, 1000, wakeup_.fd());
318
318
  if (resp.empty()) continue;
319
319
 
@@ -334,8 +334,8 @@ bool UpnpClient::discover_device(Device& out) {
334
334
  if (std::find(tried.begin(), tried.end(), location) != tried.end()) continue;
335
335
  tried.push_back(location);
336
336
 
337
- std::string local_ip = local_ip_for_destination(from.ip, from.port);
338
- LOG_UPNP_DEBUG("SSDP reply from " << from.ip << " location=" << location);
337
+ std::string local_ip = local_ip_for_destination(from.ip.to_string(), from.port);
338
+ LOG_UPNP_DEBUG("SSDP reply from " << from.ip.to_string() << " location=" << location);
339
339
  if (fetch_description(location, local_ip, out)) {
340
340
  found = true;
341
341
  break;
@@ -18,8 +18,8 @@
18
18
  * external XML/HTTP libraries) using librats' own socket primitives.
19
19
  */
20
20
 
21
- #include "port_mapping.h"
22
- #include "wakeup_pipe.h"
21
+ #include "librats/nat/port_mapping.h"
22
+ #include "librats/core/wakeup_pipe.h"
23
23
 
24
24
  #include <atomic>
25
25
  #include <condition_variable>
@@ -0,0 +1,84 @@
1
+ #pragma once
2
+
3
+ /**
4
+ * @file circuit_service.h
5
+ * @brief Turning a relayed byte stream into a peer connection — the capability a
6
+ * relay module needs and PeerNetwork deliberately does not offer.
7
+ *
8
+ * A relay module speaks a protocol (who forwards what to whom) and owns the byte
9
+ * stream that comes out of it (transport/relay_link.h). What it cannot do on its
10
+ * own is the one remaining step: making that stream a Connection, so the ordinary
11
+ * Noise handshake, framing, identify and peer table all run over it and the peer
12
+ * at the far end becomes an ordinary peer. That step needs the reactor pool, which
13
+ * a Subsystem has no business holding.
14
+ *
15
+ * So this is the narrow escape hatch, published by the Node in its ServiceRegistry
16
+ * next to DialService, and resolved by whoever needs it:
17
+ *
18
+ * if (auto* circuits = ctx.services.get<CircuitService>())
19
+ * auto route = circuits->adopt_circuit(relay_id, std::move(link),
20
+ * ConnRole::Outbound, false);
21
+ *
22
+ * ── One thread, chosen for you ──────────────────────────────────────────────
23
+ * The node places the circuit on the reactor that owns the CARRIER's connection,
24
+ * and that is the whole reason this call exists rather than a bare "adopt this
25
+ * link somewhere". Every byte of a circuit arrives on the carrier's connection and
26
+ * leaves through it, so putting the two on one thread means the entire relayed
27
+ * path is handled without a lock, a queue or a hand-off — the same shared-nothing
28
+ * property every other connection has. Any other placement would move bytes
29
+ * between reactor threads twice per message.
30
+ *
31
+ * The route comes back synchronously (the ConnId is reserved before the adoption
32
+ * is posted, exactly as Reactor::connect does), so the caller can wake and close
33
+ * the circuit from the moment it asks for one.
34
+ *
35
+ * ── What is deliberately NOT here ───────────────────────────────────────────
36
+ * Nothing about relaying: no relay selection, no protocol, no policy about when a
37
+ * circuit is worth opening. Those belong to the module. This interface would serve
38
+ * any transport that arrives from outside the reactor pool.
39
+ */
40
+
41
+ #include "librats/core/types.h"
42
+ #include "librats/peer/peer_id.h"
43
+ #include "librats/peer/peer_table.h" // PeerRoute
44
+ #include "librats/transport/link.h"
45
+
46
+ #include <cstdint>
47
+ #include <memory>
48
+ #include <optional>
49
+
50
+ namespace librats {
51
+
52
+ class CircuitService {
53
+ public:
54
+ virtual ~CircuitService() = default;
55
+
56
+ /// Adopt `link` as a connection carried by the peer `carrier`, on the reactor
57
+ /// that owns the carrier's own connection.
58
+ ///
59
+ /// @param role Outbound for a circuit we opened, Inbound for one opened to
60
+ /// us. It is what the secure handshake and the peer table's
61
+ /// duplicate resolution read, so it must say who asked.
62
+ /// @param connected whether the far end is already there. An inbound circuit is
63
+ /// (the opener would not have sent it otherwise); an outbound
64
+ /// one is not until its acceptance arrives, and until then the
65
+ /// connection waits in Connecting for a PollOut.
66
+ /// @return the new connection's route, or nullopt when the carrier is no longer
67
+ /// a peer, or when an inbound circuit would push this node past its peer
68
+ /// limit. Nothing is started in that case and `link` is released.
69
+ virtual std::optional<PeerRoute> adopt_circuit(const PeerId& carrier,
70
+ std::unique_ptr<Link> link,
71
+ ConnRole role, bool connected) = 0;
72
+
73
+ /// Deliver poll-equivalent events (PollIn / PollOut / PollErr, see
74
+ /// core/io_poller.h) to a circuit connection — the events a socket-backed link
75
+ /// would have got from the poller. Thread-safe, and a no-op for a route that is
76
+ /// already gone.
77
+ virtual void wake_circuit(PeerRoute route, uint32_t events) = 0;
78
+
79
+ /// Tear a circuit connection down. Thread-safe; a no-op for a route that is
80
+ /// already gone.
81
+ virtual void close_circuit(PeerRoute route, CloseReason reason) = 0;
82
+ };
83
+
84
+ } // namespace librats
@@ -0,0 +1,110 @@
1
+ #pragma once
2
+
3
+ /**
4
+ * @file config.h
5
+ * @brief Node construction options.
6
+ */
7
+
8
+ #include "librats/util/rats_export.h"
9
+ #include "librats/core/types.h" // TransportKind
10
+
11
+ #include <cstdint>
12
+ #include <string>
13
+
14
+ namespace librats {
15
+
16
+ struct RATS_API NodeConfig {
17
+ /// Listen port for inbound peers. 0 picks an ephemeral port. Ignored if
18
+ /// enable_listen is false (client-only node). Both transports use this same
19
+ /// port, so one advertised address is dialable over either.
20
+ uint16_t listen_port = 0;
21
+ bool enable_listen = true;
22
+
23
+ // ── Transports ──────────────────────────────────────────────────────────
24
+ //
25
+ // TCP and UDP are equal citizens here: identical framing, identical Noise
26
+ // handshake, identical guarantees. They differ only in how the ordered,
27
+ // reliable byte stream underneath is obtained — the kernel's TCP stack, or
28
+ // the library's own reliability layer over datagrams (transport/udp_stream.h).
29
+ // A node normally offers both and lets each dial pick.
30
+
31
+ /// Accept and dial over TCP.
32
+ bool enable_tcp = true;
33
+ /// Accept and dial over the datagram transport. Also gives a dial-only node a
34
+ /// single UDP socket to dial from, which is what keeps one NAT mapping open
35
+ /// for every peer instead of one per peer.
36
+ bool enable_udp = true;
37
+
38
+ /// Which transport a dial tries first.
39
+ ///
40
+ /// UDP is the default because it is the better fit for peer-to-peer: every
41
+ /// peer shares one socket and therefore one NAT mapping, the port a peer sees
42
+ /// us send from is the port it can dial back, which is what makes hole
43
+ /// punching possible at all, and no middlebox holds per-connection state that
44
+ /// can be exhausted or timed out from under us. TCP remains a first-class
45
+ /// equal, and is what the fallback below exists for — some networks block or
46
+ /// throttle UDP outright.
47
+ TransportKind preferred_transport = TransportKind::Udp;
48
+
49
+ /// How long the preferred transport dials alone before the other one is
50
+ /// raced alongside it. The first to complete its handshake wins and the loser
51
+ /// is dropped, so a UDP-blocking network costs this delay rather than a failed
52
+ /// connection. 0 disables the fallback: only the preferred transport is tried.
53
+ uint32_t transport_fallback_ms = 1200;
54
+
55
+ /// Bytes a peer's send queue may hold before the peer is dropped as a slow
56
+ /// consumer. 0 uses the library default (8 MiB).
57
+ ///
58
+ /// A quarter of this is the mark at which send() starts answering "no room"
59
+ /// and on_peer_writable is what says the room is back — so lowering it makes
60
+ /// an application feel backpressure sooner, and raising it lets a bursty one
61
+ /// buffer more before anything is said. The two move together on purpose:
62
+ /// a warning that arrives at the same moment as the disconnection is no
63
+ /// warning at all.
64
+ size_t send_queue_limit = 0;
65
+
66
+ /// Interface to bind the listener to. The address family is derived from it:
67
+ /// - "" or "::" → dual-stack wildcard: reachable over both IPv6 and IPv4
68
+ /// (IPv4-mapped) on all interfaces. This is the default.
69
+ /// - "0.0.0.0" → IPv4 on all interfaces.
70
+ /// - an IPv6 literal → IPv6-only, that interface (e.g. "::1" for v6 loopback).
71
+ /// - an IPv4 literal → IPv4, that interface (e.g. "127.0.0.1" for v4 loopback).
72
+ /// Bare IPv6 literals are written without brackets here; peer endpoints rendered
73
+ /// as text use bracketed "[ip]:port" form (see core/address.h).
74
+ std::string bind_address = "";
75
+
76
+ /// Number of reactor threads. 1 is plenty for thousands of peers; larger
77
+ /// pools shard outbound connections across cores.
78
+ size_t reactor_threads = 1;
79
+
80
+ /// Maximum number of established peers. 0 means unlimited. The limit guards
81
+ /// inbound connections (a flood is refused at accept, before any handshake);
82
+ /// outbound dials we initiate are always honored. Runtime-adjustable via
83
+ /// Node::set_max_peers().
84
+ size_t max_peers = 0;
85
+
86
+ /// Secure channel to use for peer connections.
87
+ enum class Security { Noise, Plaintext };
88
+ Security security = Security::Noise;
89
+
90
+ /// Application protocol identity, bound into the Noise handshake prologue, so
91
+ /// two nodes whose protocol differs cannot complete a handshake — a cheap,
92
+ /// cryptographically-enforced way to keep separate apps (or app versions)
93
+ /// from cross-connecting. An opaque string compared for exact equality; by
94
+ /// convention "<name>/<version>". Both peers must match. (Under Plaintext it
95
+ /// is still checked, but not cryptographically bound — see PlaintextSecurity.)
96
+ std::string protocol = "librats/1.0";
97
+
98
+ /// Directory for persistent state. Empty = ephemeral (a fresh random
99
+ /// identity each run). When set, the node's Noise keypair is loaded from /
100
+ /// saved to "<data_dir>/identity.key", giving a stable PeerId across restarts.
101
+ std::string data_dir = "";
102
+
103
+ /// Watch the host for network configuration changes (interface up/down, IP
104
+ /// add/remove, route flip, wake-from-sleep) and publish NetworkChanged on the
105
+ /// node's EventBus so subsystems can renew port mappings, re-run STUN and
106
+ /// re-announce. Costs one mostly-idle monitor thread. See node/host_events.h.
107
+ bool enable_network_monitor = true;
108
+ };
109
+
110
+ } // namespace librats
@@ -0,0 +1,54 @@
1
+ #pragma once
2
+
3
+ /**
4
+ * @file dial_service.h
5
+ * @brief Dialing a specific endpoint over a specific wire — the capability a
6
+ * NAT-traversal module needs and the ordinary connect() cannot express.
7
+ *
8
+ * PeerNetwork::connect(Address) is deliberately opinionated: it hands the target to
9
+ * the Dialer, which picks a transport, races the other one in after the fallback
10
+ * delay, and remembers what it learned for next time (see node/dialer.h). That is
11
+ * exactly right for "connect me to this peer" and exactly wrong for a hole punch,
12
+ * which needs three things the race cannot give:
13
+ *
14
+ * - the datagram wire and nothing else. A punch is only possible on the shared
15
+ * UDP socket; racing TCP alongside it spends a connect attempt on a path that
16
+ * a NAT will refuse by construction.
17
+ * - a dial that starts NOW, at a moment agreed with the peer. A punch works
18
+ * because two Syns cross mid-path; a fallback delay measured from our own clock
19
+ * has nothing to do with that instant.
20
+ * - a different retry shape (see DialProfile) — dense probes rather than a long
21
+ * patient tail, because the early Syns are *expected* to die on the peer's NAT.
22
+ *
23
+ * So this is the narrow escape hatch, published by the Node in its ServiceRegistry
24
+ * and resolved by whoever needs it:
25
+ *
26
+ * if (auto* dial = ctx.services.get<DialService>())
27
+ * dial->dial_direct(addr, TransportKind::Udp, DialProfile::punch());
28
+ *
29
+ * It is deliberately *not* on PeerNetwork: every subsystem sees that interface, and
30
+ * "dial exactly this, exactly this way" is a capability one module needs rather than
31
+ * a contract all of them should have. Everything else about the resulting connection
32
+ * is ordinary — the same handshake, the same identify, the same duplicate resolution
33
+ * in PeerTable if the peer dialed us back at the same moment.
34
+ */
35
+
36
+ #include "librats/core/address.h"
37
+ #include "librats/core/types.h"
38
+
39
+ namespace librats {
40
+
41
+ class DialService {
42
+ public:
43
+ virtual ~DialService() = default;
44
+
45
+ /// Start exactly one dial to `addr` over `kind`, bypassing the transport race.
46
+ /// Non-blocking; the outcome surfaces through the node's ordinary peer-connected
47
+ /// event. Returns false when the node cannot carry that transport at all (no
48
+ /// datagram socket, or an address family the one socket cannot reach), in which
49
+ /// case nothing was started and no failure event will follow.
50
+ virtual bool dial_direct(const Address& addr, TransportKind kind,
51
+ const DialProfile& profile) = 0;
52
+ };
53
+
54
+ } // namespace librats