librats 1.0.2 → 2.1.4

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 (313) hide show
  1. package/README.md +137 -332
  2. package/binding.gyp +16 -3
  3. package/lib/index.d.ts +271 -696
  4. package/lib/index.js +383 -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 +396 -179
  8. package/native-src/LICENSE +1 -1
  9. package/native-src/src/librats/bindings/rats.cpp +731 -0
  10. package/native-src/src/librats/bindings/rats.h +352 -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 +42 -0
  73. package/native-src/src/librats/core/types.h +93 -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/config.h +110 -0
  144. package/native-src/src/librats/node/dial_service.h +54 -0
  145. package/native-src/src/librats/node/dialer.cpp +264 -0
  146. package/native-src/src/librats/node/dialer.h +188 -0
  147. package/native-src/src/librats/node/host_events.h +26 -0
  148. package/native-src/src/librats/node/identify.cpp +130 -0
  149. package/native-src/src/librats/node/identify.h +71 -0
  150. package/native-src/src/librats/node/nat_status.cpp +103 -0
  151. package/native-src/src/librats/node/nat_status.h +118 -0
  152. package/native-src/src/librats/node/node.cpp +826 -0
  153. package/native-src/src/librats/node/node.h +333 -0
  154. package/native-src/src/librats/node/node_context.h +33 -0
  155. package/native-src/src/librats/node/peer_network.h +91 -0
  156. package/native-src/src/librats/peer/peer.h +49 -0
  157. package/native-src/src/librats/peer/peer_book.cpp +181 -0
  158. package/native-src/src/librats/peer/peer_book.h +88 -0
  159. package/native-src/src/librats/peer/peer_id.cpp +72 -0
  160. package/native-src/src/librats/peer/peer_id.h +62 -0
  161. package/native-src/src/librats/peer/peer_info.h +37 -0
  162. package/native-src/src/librats/peer/peer_table.cpp +137 -0
  163. package/native-src/src/librats/peer/peer_table.h +148 -0
  164. package/native-src/src/librats/security/handshaker.h +66 -0
  165. package/native-src/src/librats/security/identity.h +43 -0
  166. package/native-src/src/librats/security/noise_security.cpp +122 -0
  167. package/native-src/src/librats/security/noise_security.h +37 -0
  168. package/native-src/src/librats/security/plaintext_security.h +106 -0
  169. package/native-src/src/librats/security/session.h +37 -0
  170. package/native-src/src/{storage.cpp → librats/storage/storage.cpp} +369 -522
  171. package/native-src/src/{storage.h → librats/storage/storage.h} +135 -299
  172. package/native-src/src/librats/subsystems/bittorrent.cpp +211 -0
  173. package/native-src/src/librats/subsystems/bittorrent.h +136 -0
  174. package/native-src/src/librats/subsystems/dht_discovery.cpp +202 -0
  175. package/native-src/src/librats/subsystems/dht_discovery.h +123 -0
  176. package/native-src/src/librats/subsystems/dht_service.h +36 -0
  177. package/native-src/src/librats/subsystems/file_transfer.cpp +972 -0
  178. package/native-src/src/librats/subsystems/file_transfer.h +367 -0
  179. package/native-src/src/librats/subsystems/hole_punch.cpp +532 -0
  180. package/native-src/src/librats/subsystems/hole_punch.h +266 -0
  181. package/native-src/src/librats/subsystems/hole_punch_service.h +38 -0
  182. package/native-src/src/librats/subsystems/mdns_discovery.cpp +66 -0
  183. package/native-src/src/librats/subsystems/mdns_discovery.h +55 -0
  184. package/native-src/src/librats/subsystems/message_json.cpp +112 -0
  185. package/native-src/src/librats/subsystems/message_json.h +88 -0
  186. package/native-src/src/librats/subsystems/peer_exchange.cpp +241 -0
  187. package/native-src/src/librats/subsystems/peer_exchange.h +136 -0
  188. package/native-src/src/librats/subsystems/ping_service.cpp +98 -0
  189. package/native-src/src/librats/subsystems/ping_service.h +66 -0
  190. package/native-src/src/librats/subsystems/port_mapping_service.cpp +192 -0
  191. package/native-src/src/librats/subsystems/port_mapping_service.h +84 -0
  192. package/native-src/src/librats/subsystems/pubsub.cpp +567 -0
  193. package/native-src/src/librats/subsystems/pubsub.h +175 -0
  194. package/native-src/src/librats/subsystems/reconnection.cpp +239 -0
  195. package/native-src/src/librats/subsystems/reconnection.h +126 -0
  196. package/native-src/src/librats/transport/connection.cpp +343 -0
  197. package/native-src/src/librats/transport/connection.h +283 -0
  198. package/native-src/src/librats/transport/link.h +96 -0
  199. package/native-src/src/librats/transport/reactor.cpp +540 -0
  200. package/native-src/src/librats/transport/reactor.h +224 -0
  201. package/native-src/src/librats/transport/reactor_pool.h +81 -0
  202. package/native-src/src/librats/transport/tcp_link.cpp +49 -0
  203. package/native-src/src/librats/transport/tcp_link.h +43 -0
  204. package/native-src/src/librats/transport/udp_mux.cpp +617 -0
  205. package/native-src/src/librats/transport/udp_mux.h +363 -0
  206. package/native-src/src/librats/transport/udp_packet.cpp +121 -0
  207. package/native-src/src/librats/transport/udp_packet.h +190 -0
  208. package/native-src/src/librats/transport/udp_stream.cpp +1194 -0
  209. package/native-src/src/librats/transport/udp_stream.h +614 -0
  210. package/native-src/src/librats/util/features.h.in +51 -0
  211. package/native-src/src/{fs.cpp → librats/util/fs.cpp} +51 -3
  212. package/native-src/src/librats/util/fs.h +136 -0
  213. package/native-src/src/librats/util/json.cpp +1002 -0
  214. package/native-src/src/librats/util/json.h +444 -0
  215. package/native-src/src/{logger.cpp → librats/util/logger.cpp} +1 -1
  216. package/native-src/src/{logger.h → librats/util/logger.h} +43 -31
  217. package/native-src/src/{network_monitor.cpp → librats/util/network_monitor.cpp} +12 -4
  218. package/native-src/src/{network_monitor.h → librats/util/network_monitor.h} +2 -1
  219. package/native-src/src/{network_utils.cpp → librats/util/network_utils.cpp} +38 -23
  220. package/native-src/src/{network_utils.h → librats/util/network_utils.h} +15 -8
  221. package/native-src/src/{os.cpp → librats/util/os.cpp} +48 -18
  222. package/native-src/src/librats/util/rats_export.h +69 -0
  223. package/native-src/src/{version.cpp → librats/util/version.cpp} +2 -2
  224. package/native-src/src/{version.h.in → librats/util/version.h.in} +1 -1
  225. package/native-src/src/librats/wire/frame.cpp +76 -0
  226. package/native-src/src/librats/wire/frame.h +110 -0
  227. package/native-src/src/librats/wire/message_router.cpp +45 -0
  228. package/native-src/src/librats/wire/message_router.h +47 -0
  229. package/package.json +5 -4
  230. package/scripts/build-librats.js +1 -0
  231. package/scripts/postinstall.js +3 -3
  232. package/scripts/prepare-package.js +4 -4
  233. package/scripts/verify-installation.js +63 -105
  234. package/src/librats_node.cpp +1042 -1324
  235. package/native-src/src/bencode.cpp +0 -485
  236. package/native-src/src/bencode.h +0 -145
  237. package/native-src/src/bittorrent.cpp +0 -14
  238. package/native-src/src/bittorrent.h +0 -74
  239. package/native-src/src/bt_bitfield.cpp +0 -372
  240. package/native-src/src/bt_bitfield.h +0 -316
  241. package/native-src/src/bt_choker.cpp +0 -228
  242. package/native-src/src/bt_choker.h +0 -147
  243. package/native-src/src/bt_client.cpp +0 -1047
  244. package/native-src/src/bt_client.h +0 -445
  245. package/native-src/src/bt_create_torrent.cpp +0 -677
  246. package/native-src/src/bt_create_torrent.h +0 -473
  247. package/native-src/src/bt_extension.cpp +0 -469
  248. package/native-src/src/bt_extension.h +0 -309
  249. package/native-src/src/bt_file_storage.cpp +0 -261
  250. package/native-src/src/bt_file_storage.h +0 -298
  251. package/native-src/src/bt_handshake.cpp +0 -134
  252. package/native-src/src/bt_handshake.h +0 -157
  253. package/native-src/src/bt_messages.cpp +0 -364
  254. package/native-src/src/bt_messages.h +0 -324
  255. package/native-src/src/bt_network.cpp +0 -1007
  256. package/native-src/src/bt_network.h +0 -417
  257. package/native-src/src/bt_peer_connection.cpp +0 -742
  258. package/native-src/src/bt_peer_connection.h +0 -592
  259. package/native-src/src/bt_piece_picker.cpp +0 -786
  260. package/native-src/src/bt_piece_picker.h +0 -473
  261. package/native-src/src/bt_resume_data.cpp +0 -410
  262. package/native-src/src/bt_resume_data.h +0 -249
  263. package/native-src/src/bt_torrent.cpp +0 -2120
  264. package/native-src/src/bt_torrent.h +0 -641
  265. package/native-src/src/bt_torrent_info.cpp +0 -659
  266. package/native-src/src/bt_torrent_info.h +0 -418
  267. package/native-src/src/bt_types.h +0 -621
  268. package/native-src/src/chained_send_buffer.cpp +0 -75
  269. package/native-src/src/chained_send_buffer.h +0 -137
  270. package/native-src/src/crypto/hkdf.c +0 -266
  271. package/native-src/src/crypto/poly1305.h +0 -36
  272. package/native-src/src/dht.cpp +0 -3311
  273. package/native-src/src/dht.h +0 -717
  274. package/native-src/src/disk_io.cpp +0 -632
  275. package/native-src/src/disk_io.h +0 -315
  276. package/native-src/src/file_transfer.cpp +0 -1415
  277. package/native-src/src/file_transfer.h +0 -286
  278. package/native-src/src/fs.h +0 -108
  279. package/native-src/src/gossipsub.cpp +0 -1139
  280. package/native-src/src/gossipsub.h +0 -403
  281. package/native-src/src/ice.cpp +0 -893
  282. package/native-src/src/ice.h +0 -559
  283. package/native-src/src/json.hpp +0 -25526
  284. package/native-src/src/librats.cpp +0 -2378
  285. package/native-src/src/librats.h +0 -2324
  286. package/native-src/src/librats_bittorrent.cpp +0 -601
  287. package/native-src/src/librats_c.cpp +0 -1557
  288. package/native-src/src/librats_c.h +0 -323
  289. package/native-src/src/librats_discovery.cpp +0 -402
  290. package/native-src/src/librats_encryption.cpp +0 -275
  291. package/native-src/src/librats_file_transfer.cpp +0 -144
  292. package/native-src/src/librats_gossipsub.cpp +0 -289
  293. package/native-src/src/librats_ice.cpp +0 -213
  294. package/native-src/src/librats_log_macros.h +0 -36
  295. package/native-src/src/librats_logging.cpp +0 -173
  296. package/native-src/src/librats_mdns.cpp +0 -166
  297. package/native-src/src/librats_persistence.cpp +0 -796
  298. package/native-src/src/librats_portmap.cpp +0 -419
  299. package/native-src/src/librats_reconnection.cpp +0 -218
  300. package/native-src/src/librats_statistic.cpp +0 -105
  301. package/native-src/src/librats_storage.cpp +0 -189
  302. package/native-src/src/rats_export.h +0 -17
  303. package/native-src/src/receive_buffer.cpp +0 -82
  304. package/native-src/src/receive_buffer.h +0 -127
  305. package/native-src/src/socket.h +0 -228
  306. package/native-src/src/threadmanager.cpp +0 -105
  307. package/native-src/src/threadmanager.h +0 -53
  308. package/native-src/src/tracker.cpp +0 -1264
  309. package/native-src/src/tracker.h +0 -319
  310. package/native-src/src/turn.cpp +0 -762
  311. package/native-src/src/turn.h +0 -460
  312. package/native-src/src/wakeup_pipe.h +0 -60
  313. /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