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,402 +0,0 @@
1
- #include "librats.h"
2
- #include "librats_log_macros.h"
3
- #include "sha1.h"
4
-
5
- namespace librats {
6
-
7
- // =========================================================================
8
- // Peer Discovery Methods
9
- // =========================================================================
10
-
11
- bool RatsClient::start_dht_discovery(int dht_port) {
12
- if (dht_client_ && dht_client_->is_running()) {
13
- LOG_CLIENT_WARN("DHT discovery is already running");
14
- return true;
15
- }
16
-
17
- LOG_CLIENT_INFO("Starting DHT discovery on port " << dht_port <<
18
- (bind_address_.empty() ? "" : " bound to " + bind_address_));
19
-
20
- auto bootstrap_nodes = DhtClient::get_default_bootstrap_nodes();
21
-
22
- // IPv4 DHT (also shared with the BitTorrent subsystem) - required.
23
- dht_client_ = std::make_unique<DhtClient>(dht_port, bind_address_, data_directory_, AddressFamily::IPv4);
24
- if (!dht_client_->start()) {
25
- LOG_CLIENT_ERROR("Failed to start IPv4 DHT client");
26
- dht_client_.reset();
27
- return false;
28
- }
29
- if (!dht_client_->bootstrap(bootstrap_nodes)) {
30
- LOG_CLIENT_WARN("Failed to bootstrap IPv4 DHT");
31
- }
32
-
33
- // IPv6 DHT - best effort. Shares the same port via a V6ONLY socket. If the host has
34
- // no usable IPv6 stack, socket creation fails and we simply run IPv4-only.
35
- dht_client_v6_ = std::make_unique<DhtClient>(dht_port, bind_address_, data_directory_, AddressFamily::IPv6);
36
- if (dht_client_v6_->start()) {
37
- if (!dht_client_v6_->bootstrap(bootstrap_nodes)) {
38
- LOG_CLIENT_WARN("Failed to bootstrap IPv6 DHT");
39
- }
40
- LOG_CLIENT_INFO("IPv6 DHT client started");
41
- } else {
42
- LOG_CLIENT_INFO("IPv6 DHT unavailable on this host, running IPv4-only");
43
- dht_client_v6_.reset();
44
- }
45
-
46
- // Forward the DHT's UDP port through the router, in addition to the TCP peer
47
- // port mapped at start(). Like libtorrent (which maps both the TCP listen port
48
- // and the UDP DHT/uTP port per listen socket), this makes the node reachable by
49
- // inbound DHT traffic behind NAT. No-op when port mapping is disabled; the
50
- // mapping uses external==internal so outgoing queries and inbound packets share
51
- // one public port. The backends wake their workers to install it immediately.
52
- // Use the *actual* bound port: start() may have fallen back to an ephemeral one
53
- // when the requested dht_port was taken.
54
- uint16_t bound_dht_port = dht_client_->get_port();
55
- if (bound_dht_port != 0) {
56
- add_port_mapping(PortMapProtocol::UDP, bound_dht_port);
57
- }
58
-
59
- // Start automatic peer discovery (this thread also performs the best-effort STUN probe
60
- // that derives our BEP 42 node ID — see automatic_discovery_loop).
61
- start_automatic_peer_discovery();
62
-
63
- LOG_CLIENT_INFO("DHT discovery started successfully");
64
- return true;
65
- }
66
-
67
- void RatsClient::stop_dht_discovery() {
68
- if (!dht_client_ && !dht_client_v6_) {
69
- return;
70
- }
71
-
72
- LOG_CLIENT_INFO("Stopping DHT discovery");
73
-
74
- // Stop automatic peer discovery
75
- stop_automatic_peer_discovery();
76
-
77
- if (dht_client_) {
78
- dht_client_->stop();
79
- dht_client_.reset();
80
- }
81
- if (dht_client_v6_) {
82
- dht_client_v6_->stop();
83
- dht_client_v6_.reset();
84
- }
85
- LOG_CLIENT_INFO("DHT discovery stopped");
86
- }
87
-
88
- bool RatsClient::find_peers_by_hash(const std::string& content_hash, std::function<void(const std::vector<std::string>&)> callback) {
89
- if (!is_dht_running()) {
90
- LOG_CLIENT_ERROR("DHT client not running");
91
- return false;
92
- }
93
-
94
- if (content_hash.length() != CONTENT_HASH_HEX_LENGTH) {
95
- LOG_CLIENT_ERROR("Invalid content hash length: " << content_hash.length() << " (expected " << CONTENT_HASH_HEX_LENGTH << ")");
96
- return false;
97
- }
98
-
99
- LOG_CLIENT_INFO("Finding peers for content hash: " << content_hash);
100
-
101
- InfoHash info_hash = hex_to_node_id(content_hash);
102
-
103
- // Shared wrapper: discovered peers (IPv4 or IPv6) are delivered through the same callback.
104
- PeerDiscoveryCallback peer_callback = [callback](const std::vector<Peer>& peers, const InfoHash&) {
105
- std::vector<std::string> peer_addresses;
106
- peer_addresses.reserve(peers.size());
107
- for (const auto& peer : peers) {
108
- peer_addresses.emplace_back(peer.ip + ":" + std::to_string(peer.port));
109
- }
110
- if (callback) {
111
- callback(peer_addresses);
112
- }
113
- };
114
-
115
- // Fan out to both Kademlia networks; succeed if at least one accepts the search.
116
- bool started = false;
117
- if (dht_client_ && dht_client_->is_running()) {
118
- started |= dht_client_->find_peers(info_hash, peer_callback);
119
- }
120
- if (dht_client_v6_ && dht_client_v6_->is_running()) {
121
- started |= dht_client_v6_->find_peers(info_hash, peer_callback);
122
- }
123
- return started;
124
- }
125
-
126
- bool RatsClient::announce_for_hash(const std::string& content_hash, uint16_t port,
127
- std::function<void(const std::vector<std::string>&)> callback) {
128
- if (!is_dht_running()) {
129
- LOG_CLIENT_ERROR("DHT client not running");
130
- return false;
131
- }
132
-
133
- if (content_hash.length() != CONTENT_HASH_HEX_LENGTH) {
134
- LOG_CLIENT_ERROR("Invalid content hash length: " << content_hash.length() << " (expected " << CONTENT_HASH_HEX_LENGTH << ")");
135
- return false;
136
- }
137
-
138
- if (port == 0) {
139
- port = listen_port_;
140
- }
141
-
142
- LOG_CLIENT_INFO("Announcing for content hash: " << content_hash << " on port " << port
143
- << (callback ? " with peer callback" : ""));
144
-
145
- InfoHash info_hash = hex_to_node_id(content_hash);
146
-
147
- // Create wrapper callback that converts Peer to string addresses (if callback provided)
148
- PeerDiscoveryCallback peer_callback = nullptr;
149
- if (callback) {
150
- peer_callback = [callback](const std::vector<Peer>& peers, const InfoHash& hash) {
151
- std::vector<std::string> peer_addresses;
152
- peer_addresses.reserve(peers.size());
153
- for (const auto& peer : peers) {
154
- peer_addresses.push_back(peer.ip + ":" + std::to_string(peer.port));
155
- }
156
- callback(peer_addresses);
157
- };
158
- }
159
-
160
- // Announce on both Kademlia networks so IPv4 and IPv6 peers can both find us.
161
- bool started = false;
162
- if (dht_client_ && dht_client_->is_running()) {
163
- started |= dht_client_->announce_peer(info_hash, port, peer_callback);
164
- }
165
- if (dht_client_v6_ && dht_client_v6_->is_running()) {
166
- started |= dht_client_v6_->announce_peer(info_hash, port, peer_callback);
167
- }
168
- return started;
169
- }
170
-
171
- bool RatsClient::is_dht_running() const {
172
- return (dht_client_ && dht_client_->is_running()) ||
173
- (dht_client_v6_ && dht_client_v6_->is_running());
174
- }
175
-
176
- size_t RatsClient::get_dht_routing_table_size() const {
177
- size_t total = 0;
178
- if (dht_client_) {
179
- total += dht_client_->get_routing_table_size();
180
- }
181
- if (dht_client_v6_) {
182
- total += dht_client_v6_->get_routing_table_size();
183
- }
184
- return total;
185
- }
186
-
187
- void RatsClient::handle_dht_peer_discovery(const std::vector<Peer>& peers, const InfoHash& info_hash) {
188
- LOG_CLIENT_INFO("DHT discovered " << peers.size() << " peers for info hash: " << node_id_to_hex(info_hash));
189
-
190
- // Auto-connect to discovered peers
191
- for (const auto& peer : peers) {
192
- if (!can_connect_to_peer(peer.ip, peer.port)) {
193
- continue;
194
- }
195
-
196
- LOG_CLIENT_DEBUG("Attempting to connect to discovered peer: " << peer.ip << ":" << peer.port);
197
-
198
- // Try to connect to the peer (non-blocking, managed thread for graceful shutdown)
199
- add_managed_thread(std::thread([this, peer]() {
200
- if (connect_to_peer(peer.ip, peer.port)) {
201
- LOG_CLIENT_INFO("Successfully connected to DHT discovered peer: " << peer.ip << ":" << peer.port);
202
- } else {
203
- LOG_CLIENT_DEBUG("Failed to connect to DHT discovered peer: " << peer.ip << ":" << peer.port);
204
- }
205
- }), "dht-connect-" + peer.ip);
206
- }
207
- }
208
-
209
- void RatsClient::start_automatic_peer_discovery() {
210
- if (auto_discovery_running_.load()) {
211
- LOG_CLIENT_WARN("Automatic peer discovery is already running");
212
- return;
213
- }
214
-
215
- LOG_CLIENT_INFO("Starting automatic rats peer discovery");
216
- auto_discovery_running_.store(true);
217
- auto_discovery_thread_ = std::thread(&RatsClient::automatic_discovery_loop, this);
218
- }
219
-
220
- void RatsClient::stop_automatic_peer_discovery() {
221
- if (!auto_discovery_running_.load()) {
222
- return;
223
- }
224
-
225
- LOG_CLIENT_INFO("Stopping automatic peer discovery");
226
- auto_discovery_running_.store(false);
227
-
228
- if (auto_discovery_thread_.joinable()) {
229
- auto_discovery_thread_.join();
230
- }
231
-
232
- LOG_CLIENT_INFO("Automatic peer discovery stopped");
233
- }
234
-
235
- bool RatsClient::is_automatic_discovery_running() const {
236
- return auto_discovery_running_.load();
237
- }
238
-
239
- std::chrono::seconds RatsClient::calculate_discovery_interval() const {
240
- int peer_count = get_peer_count();
241
-
242
- // No peers - aggressive discovery
243
- if (peer_count == 0) {
244
- return std::chrono::seconds(15);
245
- }
246
-
247
- // Calculate fill ratio
248
- float fill_ratio = static_cast<float>(peer_count) / static_cast<float>(max_peers_);
249
-
250
- // Graduated intervals based on fill ratio
251
- if (fill_ratio < 0.25f) {
252
- // Less than 25% full - still fairly aggressive
253
- return std::chrono::seconds(60); // 1 minute
254
- } else if (fill_ratio < 0.50f) {
255
- // 25-50% full - moderate
256
- return std::chrono::seconds(180); // 3 minutes
257
- } else if (fill_ratio < 0.75f) {
258
- // 50-75% full - relaxed
259
- return std::chrono::seconds(600); // 10 minutes
260
- } else {
261
- // 75-100% full - very relaxed (mostly just re-announcing)
262
- return std::chrono::seconds(1800); // 30 minutes
263
- }
264
- }
265
-
266
- void RatsClient::automatic_discovery_loop() {
267
- LOG_CLIENT_INFO("Automatic peer discovery loop started");
268
-
269
- // Best-effort: discover our public IP via STUN and derive a BEP 42 node ID from it BEFORE
270
- // the initial bootstrap delay below. The DHT starts receiving KRPC responses (each carrying
271
- // our address in the "ip" field) immediately on bootstrap, and that in-DHT vote can reach
272
- // EXTERNAL_IP_VOTE_THRESHOLD within a few seconds. Probing STUN first lets set_external_ip()
273
- // adopt the address and regenerate the node ID up front, so the DHT bootstraps under the
274
- // correct ID and the ip-field voting silently confirms the already-adopted address instead
275
- // of racing it to consensus. The voting remains the fallback when STUN is unavailable or the
276
- // address later changes.
277
- //
278
- // This runs on the discovery thread (not a standalone one) on purpose: stop_dht_discovery()
279
- // joins this thread via stop_automatic_peer_discovery() BEFORE resetting the DHT clients, so
280
- // set_external_ip() can never touch a destroyed DhtClient.
281
- if (auto_discovery_running_.load() && running_.load()) {
282
- auto mapped = discover_public_address("stun.l.google.com", 19302, 4000);
283
- if (mapped) {
284
- // set_external_ip validates the address family, so feeding both instances is safe:
285
- // only the matching-family DHT adopts it. (A default IPv4 STUN server yields an IPv4
286
- // address; the IPv6 node ID is learned organically from IPv6 DHT responses.)
287
- if (dht_client_) {
288
- dht_client_->set_external_ip(mapped->address);
289
- }
290
- if (dht_client_v6_) {
291
- dht_client_v6_->set_external_ip(mapped->address);
292
- }
293
- }
294
- }
295
-
296
- // Initial delay to let DHT bootstrap
297
- {
298
- std::unique_lock<std::mutex> lock(shutdown_mutex_);
299
- if (shutdown_cv_.wait_for(lock, std::chrono::seconds(INITIAL_DISCOVERY_DELAY_SECONDS), [this] { return !auto_discovery_running_.load() || !running_.load(); })) {
300
- LOG_CLIENT_INFO("Automatic peer discovery loop stopped during initial delay");
301
- return;
302
- }
303
- }
304
-
305
- // Announce immediately - this also discovers peers during traversal
306
- announce_rats_peer();
307
-
308
- auto last_announce = std::chrono::steady_clock::now();
309
-
310
- while (auto_discovery_running_.load()) {
311
- auto now = std::chrono::steady_clock::now();
312
-
313
- // Announce combines both announcing our presence and discovering peers
314
- // Interval scales based on peer count: aggressive when empty, relaxed when nearly full
315
- auto interval = calculate_discovery_interval();
316
-
317
- if (now - last_announce >= interval) {
318
- LOG_CLIENT_DEBUG("Discovery interval: " << interval.count() << "s (peers: "
319
- << get_peer_count() << "/" << max_peers_ << ")");
320
- announce_rats_peer();
321
- last_announce = now;
322
- }
323
-
324
- // Use conditional variable for responsive shutdown
325
- {
326
- std::unique_lock<std::mutex> lock(shutdown_mutex_);
327
- if (shutdown_cv_.wait_for(lock, std::chrono::milliseconds(500), [this] { return !auto_discovery_running_.load() || !running_.load(); })) {
328
- break;
329
- }
330
- }
331
- }
332
-
333
- LOG_CLIENT_INFO("Automatic peer discovery loop stopped");
334
- }
335
-
336
- void RatsClient::announce_rats_peer() {
337
- if (!dht_client_ || !dht_client_->is_running()) {
338
- LOG_CLIENT_WARN("DHT client not running, cannot announce peer");
339
- return;
340
- }
341
-
342
- std::string discovery_hash = get_discovery_hash();
343
-
344
- // Advertise the mapped public TCP port when UPnP/NAT-PMP has established one,
345
- // so WAN peers connect to (external_ip, external_port) rather than our NATed
346
- // local listen port. Falls back to listen_port_ when no mapping is active.
347
- // (Mirrors libtorrent feeding the port-mapping result into what it announces.)
348
- uint16_t announce_port = get_advertised_port();
349
- LOG_CLIENT_INFO("Announcing peer for discovery hash: " << discovery_hash << " on port " << announce_port);
350
-
351
- InfoHash info_hash = hex_to_node_id(discovery_hash);
352
-
353
- // Skip only if every running DHT network already has this announce in flight.
354
- // (announce_peer() also dedups internally, so this is just to avoid redundant work.)
355
- bool v4_busy = !dht_client_ || !dht_client_->is_running() || dht_client_->is_announce_active(info_hash);
356
- bool v6_busy = !dht_client_v6_ || !dht_client_v6_->is_running() || dht_client_v6_->is_announce_active(info_hash);
357
- if (v4_busy && v6_busy) {
358
- LOG_CLIENT_WARN("Announce already in progress for info hash: " << node_id_to_hex(info_hash));
359
- return;
360
- }
361
-
362
- // Use announce with callback - combines announce and find_peers in one traversal
363
- // Peers discovered during traversal will be returned through the callback
364
- if (announce_for_hash(discovery_hash, announce_port, [this, info_hash](const std::vector<std::string>& peer_addresses) {
365
- LOG_CLIENT_INFO("Announce discovered " << peer_addresses.size() << " peers during traversal");
366
-
367
- // Convert peer addresses to Peer objects for handle_dht_peer_discovery()
368
- std::vector<Peer> peers;
369
- peers.reserve(peer_addresses.size());
370
- for (const auto& peer_address : peer_addresses) {
371
- std::string ip;
372
- int port;
373
- if (parse_address_string(peer_address, ip, port)) {
374
- peers.push_back(Peer(ip, port));
375
- }
376
- }
377
-
378
- // Auto-connect to discovered peers
379
- if (!peers.empty()) {
380
- handle_dht_peer_discovery(peers, info_hash);
381
- }
382
- })) {
383
- LOG_CLIENT_DEBUG("Successfully started announce with peer discovery for discovery hash");
384
- } else {
385
- LOG_CLIENT_WARN("Failed to announce peer for discovery");
386
- }
387
- }
388
-
389
- std::string RatsClient::get_discovery_hash() const {
390
- std::lock_guard<std::mutex> lock(protocol_config_mutex_);
391
- // Generate discovery hash based on current protocol configuration
392
- std::string discovery_string = custom_protocol_name_ + "_peer_discovery_v" + custom_protocol_version_;
393
- return SHA1::hash(discovery_string);
394
- }
395
-
396
- std::string RatsClient::get_rats_peer_discovery_hash() {
397
- // Well-known hash for rats peer discovery
398
- // Compute SHA1 hash of "rats_peer_discovery_v1.0"
399
- return SHA1::hash("rats_peer_discovery_v1.0");
400
- }
401
-
402
- }
@@ -1,275 +0,0 @@
1
- #include "librats.h"
2
- #include "librats_log_macros.h"
3
-
4
- namespace librats {
5
-
6
- // =========================================================================
7
- // Encryption Functionality - Noise Protocol Implementation
8
- // =========================================================================
9
-
10
- void RatsClient::initialize_noise_keypair() {
11
- std::lock_guard<std::mutex> lock(encryption_mutex_);
12
- if (!noise_keypair_initialized_) {
13
- rats::noise_generate_keypair(noise_static_keypair_);
14
- noise_keypair_initialized_ = true;
15
- LOG_CLIENT_INFO("Noise Protocol static keypair generated");
16
- }
17
- }
18
-
19
- bool RatsClient::initialize_encryption(bool enable) {
20
- std::lock_guard<std::mutex> lock(encryption_mutex_);
21
- encryption_enabled_ = enable;
22
-
23
- if (enable && !noise_keypair_initialized_) {
24
- rats::noise_generate_keypair(noise_static_keypair_);
25
- noise_keypair_initialized_ = true;
26
- LOG_CLIENT_INFO("Noise Protocol initialized with new static keypair");
27
- }
28
-
29
- LOG_CLIENT_INFO("Encryption " << (enable ? "enabled" : "disabled"));
30
- return true;
31
- }
32
-
33
- void RatsClient::set_encryption_enabled(bool enabled) {
34
- std::lock_guard<std::mutex> lock(encryption_mutex_);
35
- encryption_enabled_ = enabled;
36
-
37
- if (enabled && !noise_keypair_initialized_) {
38
- rats::noise_generate_keypair(noise_static_keypair_);
39
- noise_keypair_initialized_ = true;
40
- }
41
-
42
- LOG_CLIENT_DEBUG("Encryption set to " << (enabled ? "enabled" : "disabled"));
43
- }
44
-
45
- bool RatsClient::is_encryption_enabled() const {
46
- std::lock_guard<std::mutex> lock(encryption_mutex_);
47
- return encryption_enabled_;
48
- }
49
-
50
- bool RatsClient::is_peer_encrypted(const std::string& peer_id) const {
51
- std::lock_guard<std::mutex> lock(peers_mutex_);
52
- auto it = peers_.find(peer_id);
53
- if (it != peers_.end()) {
54
- return it->second.noise_handshake_completed &&
55
- it->second.send_cipher &&
56
- it->second.recv_cipher;
57
- }
58
- return false;
59
- }
60
-
61
- bool RatsClient::set_noise_static_keypair(const uint8_t private_key[32]) {
62
- std::lock_guard<std::mutex> lock(encryption_mutex_);
63
-
64
- memcpy(noise_static_keypair_.private_key, private_key, 32);
65
- rats::noise_derive_public_key(private_key, noise_static_keypair_.public_key);
66
- noise_static_keypair_.has_keys = true;
67
- noise_keypair_initialized_ = true;
68
-
69
- LOG_CLIENT_INFO("Noise Protocol static keypair set from provided private key");
70
- return true;
71
- }
72
-
73
- std::vector<uint8_t> RatsClient::get_noise_static_public_key() const {
74
- std::lock_guard<std::mutex> lock(encryption_mutex_);
75
-
76
- if (!noise_keypair_initialized_) {
77
- return std::vector<uint8_t>();
78
- }
79
-
80
- return std::vector<uint8_t>(noise_static_keypair_.public_key,
81
- noise_static_keypair_.public_key + 32);
82
- }
83
-
84
- std::vector<uint8_t> RatsClient::get_peer_noise_public_key(const std::string& peer_id) const {
85
- std::lock_guard<std::mutex> lock(peers_mutex_);
86
- auto it = peers_.find(peer_id);
87
- if (it != peers_.end() && it->second.noise_handshake_completed) {
88
- return it->second.remote_static_key;
89
- }
90
- return std::vector<uint8_t>();
91
- }
92
-
93
- std::vector<uint8_t> RatsClient::get_peer_handshake_hash(const std::string& peer_id) const {
94
- // Handshake hash is not stored after handshake for memory efficiency
95
- // This could be added to RatsPeer if needed for channel binding
96
- (void)peer_id;
97
- return std::vector<uint8_t>();
98
- }
99
-
100
- // =========================================================================
101
- // Async Noise Handshake (non-blocking, driven by io_loop)
102
- // =========================================================================
103
-
104
- /*
105
- * Noise XX pattern (3 messages):
106
- * Initiator: write msg0 → read msg1 → write msg2 → split
107
- * Responder: read msg0 → write msg1 → read msg2 → split
108
- *
109
- * noise_step tracks where we are in this sequence:
110
- * Initiator: 0 = need write, 1 = need read, 2 = need write, 3 = done
111
- * Responder: 0 = need read, 1 = need write, 2 = need read, 3 = done
112
- *
113
- * start_noise_handshake_async() initialises noise_hs and writes the first
114
- * outgoing message (if initiator). Subsequent messages are processed by
115
- * handle_noise_frame() which is called from handle_readable when
116
- * handshake_state == NOISE_PENDING.
117
- */
118
-
119
- void RatsClient::start_noise_handshake_async(RatsPeer& peer) {
120
- LOG_CLIENT_INFO("Starting async Noise handshake for " << peer.peer_id
121
- << " (initiator: " << peer.is_outgoing << ")");
122
-
123
- // Get our static keypair
124
- rats::NoiseKeyPair static_keypair;
125
- {
126
- std::lock_guard<std::mutex> lock(encryption_mutex_);
127
- if (!noise_keypair_initialized_) {
128
- rats::noise_generate_keypair(noise_static_keypair_);
129
- noise_keypair_initialized_ = true;
130
- }
131
- memcpy(static_keypair.private_key, noise_static_keypair_.private_key, 32);
132
- memcpy(static_keypair.public_key, noise_static_keypair_.public_key, 32);
133
- static_keypair.has_keys = true;
134
- }
135
-
136
- // Allocate handshake state on the peer's IO context
137
- peer.io_.noise_hs = std::make_unique<rats::NoiseHandshakeState>();
138
- peer.io_.noise_step = 0;
139
-
140
- auto err = peer.io_.noise_hs->initialize(peer.is_outgoing, &static_keypair);
141
- if (err != rats::NoiseError::OK) {
142
- LOG_CLIENT_ERROR("Failed to initialise Noise handshake: " << static_cast<int>(err));
143
- peer.handshake_state = RatsPeer::HandshakeState::FAILED;
144
- return;
145
- }
146
-
147
- // Initiator sends message 0 immediately
148
- if (peer.is_outgoing) {
149
- uint8_t msg_buf[256];
150
- size_t msg_len = sizeof(msg_buf);
151
- err = peer.io_.noise_hs->write_message(nullptr, 0, msg_buf, &msg_len);
152
- if (err != rats::NoiseError::OK) {
153
- LOG_CLIENT_ERROR("Failed to write Noise msg 0: " << static_cast<int>(err));
154
- peer.handshake_state = RatsPeer::HandshakeState::FAILED;
155
- return;
156
- }
157
-
158
- // Enqueue as a length-prefixed frame (same framing as data messages)
159
- std::vector<uint8_t> payload(msg_buf, msg_buf + msg_len);
160
- enqueue_message_unlocked(peer, payload);
161
- peer.io_.noise_step = 1; // next: need to read msg 1
162
- LOG_CLIENT_DEBUG("Sent Noise msg 0 (" << msg_len << " bytes) to " << peer.peer_id);
163
- }
164
- // Responder waits for msg 0 from initiator (noise_step stays 0)
165
- }
166
-
167
- bool RatsClient::handle_noise_frame(RatsPeer& peer) {
168
- // The caller (handle_readable) has already verified that a complete
169
- // length-prefixed frame is available in the receive buffer, but hasn't
170
- // consumed it yet. We read the payload from recv_buf (skip 4-byte length).
171
- auto& recv_buf = peer.io_.recv_buffer;
172
-
173
- // Read payload length
174
- uint32_t net_len;
175
- memcpy(&net_len, recv_buf.data(), 4);
176
- uint32_t frame_len = ntohl(net_len);
177
-
178
- const uint8_t* frame_data = recv_buf.data() + 4;
179
-
180
- if (!peer.io_.noise_hs) {
181
- LOG_CLIENT_ERROR("Noise frame received but no handshake state for " << peer.peer_id);
182
- return false;
183
- }
184
-
185
- auto& hs = *peer.io_.noise_hs;
186
- bool is_initiator = peer.is_outgoing;
187
- rats::NoiseError err;
188
- uint8_t out_buf[256];
189
- size_t out_len;
190
-
191
- /*
192
- * Step table (noise_step → action):
193
- * Initiator: 0=write, 1=read, 2=write, 3=done
194
- * Responder: 0=read, 1=write, 2=read, 3=done
195
- *
196
- * This function is only called when we received a frame, so the current
197
- * step must expect a "read".
198
- */
199
-
200
- // ── Read the incoming Noise message ──
201
- out_len = sizeof(out_buf);
202
- err = hs.read_message(frame_data, frame_len, out_buf, &out_len);
203
- if (err != rats::NoiseError::OK) {
204
- LOG_CLIENT_ERROR("Noise read_message failed (step " << peer.io_.noise_step
205
- << "): " << static_cast<int>(err));
206
- return false;
207
- }
208
- LOG_CLIENT_DEBUG("Read Noise msg (step " << peer.io_.noise_step
209
- << ", " << frame_len << " bytes) from " << peer.peer_id);
210
-
211
- peer.io_.noise_step++;
212
-
213
- // ── If there's a reply to write, do it now ──
214
- bool need_write = false;
215
- if (is_initiator) {
216
- // Initiator writes on steps 0 and 2 → after reading (step becomes 2), write
217
- need_write = (peer.io_.noise_step == 2);
218
- } else {
219
- // Responder writes on step 1 → after reading (step becomes 1), write
220
- need_write = (peer.io_.noise_step == 1);
221
- }
222
-
223
- if (need_write) {
224
- out_len = sizeof(out_buf);
225
- err = hs.write_message(nullptr, 0, out_buf, &out_len);
226
- if (err != rats::NoiseError::OK) {
227
- LOG_CLIENT_ERROR("Noise write_message failed (step " << peer.io_.noise_step
228
- << "): " << static_cast<int>(err));
229
- return false;
230
- }
231
-
232
- std::vector<uint8_t> payload(out_buf, out_buf + out_len);
233
- enqueue_message_unlocked(peer, payload);
234
- LOG_CLIENT_DEBUG("Sent Noise msg (step " << peer.io_.noise_step
235
- << ", " << out_len << " bytes) to " << peer.peer_id);
236
- peer.io_.noise_step++;
237
- }
238
-
239
- // ── Check if handshake is complete ──
240
- if (hs.is_handshake_complete()) {
241
- auto send_cipher = std::make_shared<rats::NoiseCipherState>();
242
- auto recv_cipher = std::make_shared<rats::NoiseCipherState>();
243
-
244
- err = hs.split(*send_cipher, *recv_cipher);
245
- if (err != rats::NoiseError::OK) {
246
- LOG_CLIENT_ERROR("Noise split failed: " << static_cast<int>(err));
247
- return false;
248
- }
249
-
250
- // Store ciphers and remote static key
251
- peer.send_cipher = std::move(send_cipher);
252
- peer.recv_cipher = std::move(recv_cipher);
253
- peer.noise_handshake_completed = true;
254
-
255
- if (hs.has_remote_static()) {
256
- const uint8_t* remote_key = hs.get_remote_static_public();
257
- peer.remote_static_key.assign(remote_key, remote_key + 32);
258
- }
259
-
260
- // Free handshake state (no longer needed)
261
- peer.io_.noise_hs.reset();
262
- peer.io_.noise_step = 0;
263
-
264
- // Mark handshake completed
265
- peer.handshake_state = RatsPeer::HandshakeState::COMPLETED;
266
- validated_peer_count_.fetch_add(1, std::memory_order_relaxed);
267
- log_handshake_completion_unlocked(peer);
268
-
269
- LOG_CLIENT_INFO("Noise handshake completed with " << peer.peer_id);
270
- }
271
-
272
- return true;
273
- }
274
-
275
- } // namespace librats