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,717 +0,0 @@
1
- #pragma once
2
-
3
- #include "socket.h"
4
- #include "krpc.h"
5
- #include <string>
6
- #include <vector>
7
- #include <array>
8
- #include <unordered_map>
9
- #include <unordered_set>
10
- #include <functional>
11
- #include <thread>
12
- #include <mutex>
13
- #include <atomic>
14
- #include <chrono>
15
- #include <memory>
16
- #include <random>
17
- #include <condition_variable>
18
-
19
- // Hash specialization for Peer and NodeId (must be defined before use in unordered_map/set)
20
- namespace std {
21
- template<>
22
- struct hash<librats::Peer> {
23
- std::size_t operator()(const librats::Peer& peer) const noexcept {
24
- std::hash<std::string> hasher;
25
- return hasher(peer.ip + ":" + std::to_string(peer.port));
26
- }
27
- };
28
-
29
- template<>
30
- struct hash<array<uint8_t, 20>> {
31
- std::size_t operator()(const array<uint8_t, 20>& id) const noexcept {
32
- std::size_t seed = 0;
33
- std::hash<uint8_t> hasher;
34
- for (const auto& byte : id) {
35
- seed ^= hasher(byte) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
36
- }
37
- return seed;
38
- }
39
- };
40
- }
41
-
42
- namespace librats {
43
-
44
- // Constants for Kademlia DHT
45
- constexpr size_t NODE_ID_SIZE = 20; // 160 bits = 20 bytes
46
- constexpr size_t K_BUCKET_SIZE = 8; // Maximum nodes per k-bucket
47
- constexpr size_t ALPHA = 3; // Concurrency parameter
48
- constexpr int DHT_PORT = 6881; // Standard BitTorrent DHT port
49
-
50
- using NodeId = std::array<uint8_t, NODE_ID_SIZE>;
51
- using InfoHash = std::array<uint8_t, NODE_ID_SIZE>;
52
-
53
- /**
54
- * Search node state flags (bitfield)
55
- * Flags can be combined to track the full history of a node in a search.
56
- */
57
- namespace SearchNodeFlags {
58
- constexpr uint8_t QUERIED = 1 << 0; // Query has been sent to this node
59
- constexpr uint8_t SHORT_TIMEOUT = 1 << 1; // Node exceeded short timeout (slot freed, still waiting)
60
- constexpr uint8_t RESPONDED = 1 << 2; // Node successfully responded
61
- constexpr uint8_t TIMED_OUT = 1 << 3; // Node fully timed out (failed)
62
- constexpr uint8_t ABANDONED = 1 << 4; // Node was discarded during search truncation
63
- }
64
-
65
- /**
66
- * DHT Node information
67
- * Based on libtorrent's node_entry with fail_count and RTT tracking
68
- */
69
- struct DhtNode {
70
- NodeId id;
71
- Peer peer;
72
- std::chrono::steady_clock::time_point last_seen;
73
-
74
- // Round-trip time in milliseconds (0xffff = unknown, lower is better)
75
- uint16_t rtt = 0xffff;
76
-
77
- // Number of consecutive failures (0xff = never pinged, 0 = confirmed good)
78
- uint8_t fail_count = 0xff;
79
-
80
- DhtNode() : id(), last_seen(std::chrono::steady_clock::now()) {}
81
- DhtNode(const NodeId& id, const Peer& peer)
82
- : id(id), peer(peer), last_seen(std::chrono::steady_clock::now()) {}
83
-
84
- // Has this node ever responded to us?
85
- bool pinged() const { return fail_count != 0xff; }
86
-
87
- // Is this node confirmed good? (responded with no recent failures)
88
- bool confirmed() const { return fail_count == 0; }
89
-
90
- // Mark node as failed (timed out)
91
- void mark_failed() {
92
- if (pinged() && fail_count < 0xfe) ++fail_count;
93
- }
94
-
95
- // Mark node as successful (responded)
96
- void mark_success() {
97
- fail_count = 0;
98
- last_seen = std::chrono::steady_clock::now();
99
- }
100
-
101
- // Update RTT with exponential moving average
102
- void update_rtt(uint16_t new_rtt) {
103
- if (new_rtt == 0xffff) return;
104
- if (rtt == 0xffff) {
105
- rtt = new_rtt;
106
- } else {
107
- // Weighted average: 2/3 old + 1/3 new
108
- rtt = static_cast<uint16_t>(rtt * 2 / 3 + new_rtt / 3);
109
- }
110
- }
111
-
112
- // Compare nodes: "less" means "better" node
113
- // Priority: confirmed > not confirmed, then lower fail_count, then lower RTT
114
- bool is_worse_than(const DhtNode& other) const {
115
- // Nodes with failures are worse
116
- if (fail_count != other.fail_count) {
117
- return fail_count > other.fail_count;
118
- }
119
- // Higher RTT is worse
120
- return rtt > other.rtt;
121
- }
122
- };
123
-
124
-
125
-
126
- /**
127
- * Peer discovery callback
128
- */
129
- using PeerDiscoveryCallback = std::function<void(const std::vector<Peer>& peers, const InfoHash& info_hash)>;
130
-
131
- #ifdef RATS_SEARCH_FEATURES
132
- /**
133
- * Spider mode callback
134
- * Called when a peer announces they have a torrent (announce_peer request received)
135
- * @param info_hash The info hash being announced
136
- * @param peer The peer that is announcing (with the port they specified)
137
- */
138
- using SpiderAnnounceCallback = std::function<void(const InfoHash& info_hash, const Peer& peer)>;
139
- #endif // RATS_SEARCH_FEATURES
140
-
141
- /**
142
- * Deferred callbacks structure for avoiding deadlock
143
- * Callbacks are collected while holding the mutex, then invoked after releasing it
144
- */
145
- struct DeferredCallbacks {
146
- std::vector<PeerDiscoveryCallback> callbacks;
147
- std::vector<Peer> peers;
148
- InfoHash info_hash;
149
- bool should_invoke = false;
150
-
151
- void invoke() {
152
- if (should_invoke) {
153
- for (const auto& cb : callbacks) {
154
- if (cb) cb(peers, info_hash);
155
- }
156
- }
157
- }
158
- };
159
-
160
- /**
161
- * DHT Kademlia implementation
162
- */
163
- class DhtClient {
164
- public:
165
- /**
166
- * Constructor
167
- * @param port The UDP port to bind to (default: 6881)
168
- * @param bind_address The interface IP address to bind to (empty for all interfaces)
169
- * @param data_directory Directory for routing-table persistence
170
- * @param address_family Address family this node operates on. IPv4 and IPv6 form
171
- * separate Kademlia networks (BEP 32), so each family needs its own DhtClient.
172
- */
173
- DhtClient(int port = DHT_PORT, const std::string& bind_address = "", const std::string& data_directory = "",
174
- AddressFamily address_family = AddressFamily::IPv4);
175
-
176
- /**
177
- * Destructor
178
- */
179
- ~DhtClient();
180
-
181
- /**
182
- * Start the DHT client
183
- * @return true if successful, false otherwise
184
- */
185
- bool start();
186
-
187
- /**
188
- * Stop the DHT client
189
- */
190
- void stop();
191
-
192
- /**
193
- * Trigger immediate shutdown of all background threads
194
- */
195
- void shutdown_immediate();
196
-
197
- /**
198
- * Bootstrap the DHT with known nodes
199
- * @param bootstrap_nodes Vector of bootstrap nodes
200
- * @return true if successful, false otherwise
201
- */
202
- bool bootstrap(const std::vector<Peer>& bootstrap_nodes);
203
-
204
- /**
205
- * Find peers for a specific info hash
206
- * @param info_hash The info hash to search for
207
- * @param callback Callback to receive discovered peers
208
- * @return true if search started successfully, false otherwise
209
- */
210
- bool find_peers(const InfoHash& info_hash, PeerDiscoveryCallback callback);
211
-
212
- /**
213
- * Announce that this node is a peer for a specific info hash
214
- * @param info_hash The info hash to announce
215
- * @param port The port to announce (0 for DHT port)
216
- * @param callback Optional callback to receive discovered peers during traversal
217
- * @return true if announcement started successfully, false otherwise
218
- */
219
- bool announce_peer(const InfoHash& info_hash, uint16_t port = 0, PeerDiscoveryCallback callback = nullptr);
220
-
221
- /**
222
- * Cancel an active search or announce for a specific info hash
223
- * Should be called when a torrent is removed to clean up DHT state.
224
- * @param info_hash The info hash to cancel search for
225
- */
226
- void cancel_search(const InfoHash& info_hash);
227
-
228
- /**
229
- * Get our node ID
230
- * @return The node ID (returned by value; the ID may be regenerated at runtime
231
- * when our external IP is learned, see set_external_ip)
232
- */
233
- NodeId get_node_id() const { return node_id_; }
234
-
235
- /**
236
- * Set our external (public) IP address and regenerate the node ID from it per BEP 42.
237
- * IPv4/IPv6 node IDs must be derived from the matching-family external address, so this
238
- * is a no-op if the address family does not match this instance. Safe to call at runtime;
239
- * the routing table is re-bucketed against the new ID. Non-public/invalid addresses are ignored.
240
- * @param ip External IP address as seen by the network (e.g. from STUN or DHT "ip" voting)
241
- */
242
- void set_external_ip(const std::string& ip);
243
-
244
- /**
245
- * Get the external address currently used to derive our node ID ("" if none/random).
246
- */
247
- std::string get_external_address() const;
248
-
249
- /**
250
- * BEP 42 helpers (public for testing / explicit use).
251
- * generate_node_id_from_ip: build an IP-derived node ID (random where BEP 42 allows).
252
- * verify_node_id_for_ip: check whether a node ID is valid for the given source IP
253
- * (always true for non-public IPs, which cannot be verified).
254
- */
255
- static bool generate_node_id_from_ip(const std::string& ip, NodeId& out, std::mt19937& gen);
256
- static bool verify_node_id_for_ip(const NodeId& id, const std::string& ip);
257
-
258
- /**
259
- * Get number of nodes in routing table
260
- * @return Number of nodes
261
- */
262
- size_t get_routing_table_size() const;
263
-
264
- /**
265
- * Get number of pending ping verifications
266
- * @return Number of pending ping verifications
267
- */
268
- size_t get_pending_ping_verifications_count() const;
269
-
270
- /**
271
- * Check if a search is currently active for an info hash
272
- * @param info_hash The info hash to check
273
- * @return true if search is active, false otherwise
274
- */
275
- bool is_search_active(const InfoHash& info_hash) const;
276
-
277
- /**
278
- * Check if an announce is currently active for an info hash
279
- * @param info_hash The info hash to check
280
- * @return true if announce is active, false otherwise
281
- */
282
- bool is_announce_active(const InfoHash& info_hash) const;
283
-
284
- /**
285
- * Get number of active searches
286
- * @return Number of active searches
287
- */
288
- size_t get_active_searches_count() const;
289
-
290
- /**
291
- * Get number of active announces
292
- * @return Number of active announces
293
- */
294
- size_t get_active_announces_count() const;
295
-
296
- /**
297
- * Check if DHT is running
298
- * @return true if running, false otherwise
299
- */
300
- bool is_running() const { return running_; }
301
-
302
- /**
303
- * Actual bound UDP port. May differ from the requested port if it was taken and
304
- * the client fell back to an ephemeral port (see start()). Use this — not the
305
- * requested port — when forwarding the DHT port through a router.
306
- * @return bound port, or 0 if not started
307
- */
308
- uint16_t get_port() const { return static_cast<uint16_t>(port_); }
309
-
310
- #ifdef RATS_SEARCH_FEATURES
311
- // ============================================================================
312
- // SPIDER MODE - Aggressive node discovery and announce collection
313
- // ============================================================================
314
-
315
- /**
316
- * Enable spider mode
317
- * In spider mode:
318
- * - Nodes are added to routing table without ping verification
319
- * - All announce_peer requests from other peers are collected via callback
320
- * @param enable true to enable spider mode, false to disable
321
- */
322
- void set_spider_mode(bool enable);
323
-
324
- /**
325
- * Check if spider mode is enabled
326
- * @return true if spider mode is enabled
327
- */
328
- bool is_spider_mode() const { return spider_mode_; }
329
-
330
- /**
331
- * Set callback for announce_peer requests (spider mode)
332
- * Called when other peers announce they have a torrent
333
- * @param callback The callback to invoke
334
- */
335
- void set_spider_announce_callback(SpiderAnnounceCallback callback);
336
-
337
- /**
338
- * Set spider ignore mode - when true, incoming requests are not processed
339
- * Similar to rate limiting in the original spider implementation
340
- * @param ignore true to ignore incoming requests, false to process them
341
- */
342
- void set_spider_ignore(bool ignore);
343
-
344
- /**
345
- * Check if spider ignore mode is enabled
346
- * @return true if ignoring incoming requests
347
- */
348
- bool is_spider_ignoring() const { return spider_ignore_; }
349
-
350
- /**
351
- * Trigger a single spider walk iteration
352
- * Sends find_node to a random node from the spider pool
353
- * Should be called from external loop at desired frequency
354
- */
355
- void spider_walk();
356
-
357
- /**
358
- * Get the size of the spider node pool
359
- * @return Number of nodes in spider pool
360
- */
361
- size_t get_spider_pool_size() const;
362
-
363
- /**
364
- * Get the number of visited nodes in spider mode
365
- * @return Number of visited nodes
366
- */
367
- size_t get_spider_visited_count() const;
368
-
369
- /**
370
- * Clear spider state (pool and visited nodes)
371
- * Useful for resetting the spider walk
372
- */
373
- void clear_spider_state();
374
- #endif // RATS_SEARCH_FEATURES
375
-
376
- /**
377
- * Get default BitTorrent DHT bootstrap nodes.
378
- * Hostnames are resolved per-family at send time, so the same list serves both
379
- * IPv4 and IPv6 (nodes without an AAAA record are simply skipped on IPv6).
380
- * @return Vector of bootstrap nodes
381
- */
382
- static std::vector<Peer> get_default_bootstrap_nodes();
383
-
384
- /**
385
- * Address family this DHT node operates on.
386
- */
387
- AddressFamily address_family() const { return address_family_; }
388
- bool is_ipv6() const { return address_family_ == AddressFamily::IPv6; }
389
-
390
- /**
391
- * Compute the routing-table persistence file path for this instance.
392
- * Includes the address family so the IPv4 and IPv6 nodes (which may share a port)
393
- * never overwrite each other's saved state.
394
- */
395
- std::string routing_table_file_path() const;
396
-
397
- /**
398
- * Save routing table to disk
399
- * @return true if successful, false otherwise
400
- */
401
- bool save_routing_table();
402
-
403
- /**
404
- * Load routing table from disk
405
- * @return true if successful, false otherwise
406
- */
407
- bool load_routing_table();
408
-
409
- /**
410
- * Set data directory for persistence
411
- * @param directory Directory path
412
- */
413
- void set_data_directory(const std::string& directory);
414
-
415
- private:
416
- int port_;
417
- std::string bind_address_;
418
- std::string data_directory_;
419
- AddressFamily address_family_; // IPv4 or IPv6 (this node's Kademlia network)
420
- NodeId node_id_; // protected by routing_table_mutex_ for writes; lock-free reads are benign
421
- socket_t socket_;
422
- std::atomic<bool> running_;
423
-
424
- // BEP 42: external-IP-derived node ID.
425
- // We learn our external address from the top-level "ip" field other nodes echo back in
426
- // their responses, and vote across distinct responders before trusting it (so a single
427
- // malicious node cannot poison our node ID). external_address_/voting are guarded by
428
- // external_ip_mutex_, which is NEVER held while acquiring any other DHT mutex.
429
- std::string external_address_; // IP currently used to derive node_id_ ("" = random)
430
- std::unordered_map<std::string, int> external_ip_votes_;// reported external IP -> vote count
431
- std::unordered_set<std::string> external_ip_voters_; // responder IPs already counted (dedup)
432
- mutable std::mutex external_ip_mutex_; // Lock order: independent (never nested with others)
433
- static constexpr int EXTERNAL_IP_VOTE_THRESHOLD = 5; // distinct responders that must agree
434
- static constexpr size_t MAX_EXTERNAL_IP_VOTERS = 1000; // cap voter set to bound memory
435
-
436
- // ============================================================================
437
- // MUTEX LOCK ORDER - CRITICAL: Always acquire mutexes in this order to avoid deadlocks
438
- // ============================================================================
439
- // When acquiring multiple mutexes, ALWAYS follow this order:
440
- //
441
- // 1. pending_pings_mutex_ (Ping verification state, nodes_being_replaced_)
442
- // 2. pending_searches_mutex_ (Search state and transaction mappings)
443
- // 3. routing_table_mutex_ (core routing data)
444
- // 4. spider_nodes_mutex_ (Spider mode: node pool and visited tracking) [RATS_SEARCH_FEATURES]
445
- // 5. announced_peers_mutex_ (Stored peer data)
446
- // 6. token_secret_mutex_ (DHT write-token secret)
447
- // 7. shutdown_mutex_ (Lowest priority - can be locked independently)
448
- //
449
- // Routing table (k-buckets)
450
- std::vector<std::vector<DhtNode>> routing_table_;
451
- mutable std::mutex routing_table_mutex_; // Lock order: 3
452
-
453
- // DHT write-token secret (BEP 5). Announce tokens are SHA1(secret || querier_ip || info_hash),
454
- // so they are unforgeable (an attacker does not know the secret) and bound to BOTH the
455
- // querier's address and the specific info_hash. The secret rotates periodically; we keep the
456
- // previous secret so tokens handed out shortly before a rotation still verify. This replaces the
457
- // old, trivially forgeable std::hash("ip:port") scheme. Guarded by token_secret_mutex_, which is
458
- // a leaf lock (never held while acquiring any other DHT mutex).
459
- static constexpr int TOKEN_SECRET_ROTATION_MINUTES = 5; // acceptance window ~= 2x this
460
- std::array<uint8_t, 16> token_secret_;
461
- std::array<uint8_t, 16> token_secret_prev_;
462
- std::chrono::steady_clock::time_point token_secret_rotated_at_;
463
- std::mutex token_secret_mutex_; // Lock order: 6
464
-
465
-
466
-
467
- // Pending find_peers tracking (to map transaction IDs to info_hash)
468
- struct PendingSearch {
469
- InfoHash info_hash;
470
- std::chrono::steady_clock::time_point created_at;
471
-
472
- // Iterative search state - search_nodes is sorted by distance to info_hash (closest first)
473
- std::vector<DhtNode> search_nodes;
474
- std::vector<Peer> found_peers; // found peers for this search
475
- // Single map tracking node states using SearchNodeFlags bitfield
476
- // A node is "known" if it exists in this map (any flags set or value 0)
477
- std::unordered_map<NodeId, uint8_t> node_states;
478
-
479
- int invoke_count; // number of outstanding requests
480
- int branch_factor; // adaptive concurrency limit (starts at ALPHA)
481
- bool is_finished; // whether the search is finished
482
-
483
- // Callbacks to invoke when peers are found (supports multiple concurrent searches for same info_hash)
484
- std::vector<PeerDiscoveryCallback> callbacks;
485
-
486
- // Announce support: tokens collected during traversal (BEP 5 compliant)
487
- // Maps node_id -> write_token received from that node
488
- std::unordered_map<NodeId, std::string> write_tokens;
489
- bool is_announce; // true if this search is for announce_peer
490
- uint16_t announce_port; // port to announce (only valid if is_announce)
491
-
492
- PendingSearch(const InfoHash& hash)
493
- : info_hash(hash), created_at(std::chrono::steady_clock::now()),
494
- invoke_count(0), branch_factor(ALPHA), is_finished(false),
495
- is_announce(false), announce_port(0) {}
496
- };
497
- std::unordered_map<std::string, PendingSearch> pending_searches_; // info_hash (hex) -> PendingSearch
498
- mutable std::mutex pending_searches_mutex_; // Lock order: 2
499
-
500
- // Transaction tracking with queried node info for proper responded_nodes tracking
501
- struct SearchTransaction {
502
- std::string info_hash_hex;
503
- NodeId queried_node_id;
504
- Peer queried_endpoint; // endpoint we actually sent the query to (anti-spoofing)
505
- std::chrono::steady_clock::time_point sent_at;
506
-
507
- SearchTransaction() = default;
508
- SearchTransaction(const std::string& hash, const NodeId& id, const Peer& endpoint)
509
- : info_hash_hex(hash), queried_node_id(id), queried_endpoint(endpoint),
510
- sent_at(std::chrono::steady_clock::now()) {}
511
- };
512
- std::unordered_map<std::string, SearchTransaction> transaction_to_search_; // transaction_id -> SearchTransaction
513
-
514
- // Peer announcement storage (BEP 5 compliant)
515
- struct AnnouncedPeer {
516
- Peer peer;
517
- std::chrono::steady_clock::time_point announced_at;
518
-
519
- AnnouncedPeer(const Peer& p)
520
- : peer(p), announced_at(std::chrono::steady_clock::now()) {}
521
- };
522
- // Map from info_hash (as hex string) to list of announced peers
523
- std::unordered_map<std::string, std::vector<AnnouncedPeer>> announced_peers_;
524
- std::mutex announced_peers_mutex_; // Lock order: 5
525
-
526
- // Ping-before-replace eviction tracking (BEP 5 compliant)
527
- // When a bucket is full and a new node wants to join:
528
- // 1. We ping the WORST node in the bucket (highest RTT) to check if it's still alive
529
- // 2. If old node responds -> keep it, discard candidate
530
- // 3. If old node times out -> replace it with candidate
531
- struct PingVerification {
532
- DhtNode candidate_node; // The new node waiting to be added
533
- DhtNode old_node; // The existing node we're pinging to verify it's alive
534
- int bucket_index; // Which bucket this affects
535
- std::chrono::steady_clock::time_point ping_sent_at;
536
-
537
- PingVerification(const DhtNode& candidate, const DhtNode& old, int bucket_idx)
538
- : candidate_node(candidate), old_node(old), bucket_index(bucket_idx),
539
- ping_sent_at(std::chrono::steady_clock::now()) {}
540
- };
541
- std::unordered_map<std::string, PingVerification> pending_pings_; // transaction_id -> PingVerification
542
- std::unordered_set<NodeId> nodes_being_replaced_; // Track old nodes that have pending ping verifications
543
- mutable std::mutex pending_pings_mutex_; // Lock order: 1 (protects pending_pings_, nodes_being_replaced_)
544
-
545
- // Network thread
546
- std::thread network_thread_;
547
- std::thread maintenance_thread_;
548
-
549
- // Conditional variables for immediate shutdown
550
- std::condition_variable shutdown_cv_;
551
- std::mutex shutdown_mutex_; // Lock order: 7 (can be locked independently)
552
-
553
- #ifdef RATS_SEARCH_FEATURES
554
- // Spider mode state
555
- std::atomic<bool> spider_mode_{false};
556
- std::atomic<bool> spider_ignore_{false}; // When true, ignore incoming requests
557
- SpiderAnnounceCallback spider_announce_callback_;
558
- std::mutex spider_callbacks_mutex_; // Protects spider callbacks
559
-
560
- // Spider node tracking - separate from routing table to keep it stable
561
- std::vector<DhtNode> spider_nodes_; // Pool of nodes for spider walking
562
- std::unordered_set<NodeId> spider_visited_; // Nodes we've already queried in current session
563
- mutable std::mutex spider_nodes_mutex_; // Lock order: 4 - Protects spider_nodes_, spider_visited_, spider_transactions_, spider_contacted_ips_
564
- static constexpr size_t MAX_SPIDER_NODES = 2000; // Max nodes to keep in spider pool
565
- static constexpr size_t MAX_SPIDER_VISITED = 10000; // Max visited nodes to track
566
- static constexpr size_t MAX_SPIDER_CONTACTED_IPS = 10000; // Max contacted IPs to track
567
-
568
- // Track transactions sent in spider mode to ensure responses go to spider pool
569
- // even if spider_mode_ is disabled between request and response
570
- std::unordered_map<std::string, std::chrono::steady_clock::time_point> spider_transactions_;
571
-
572
- // Track IPs we've sent spider requests to
573
- // Used to decide whether to respond with neighbor_id (spider contact) or real node_id (organic DHT)
574
- std::unordered_set<std::string> spider_contacted_ips_;
575
-
576
- // Rate-limit re-bootstrapping in spider_walk to avoid DDOSing bootstrap nodes
577
- std::chrono::steady_clock::time_point last_spider_bootstrap_{}; // epoch = never bootstrapped
578
-
579
- // Spider helper methods
580
- void add_spider_node(const DhtNode& node);
581
- void add_spider_nodes(const std::vector<DhtNode>& nodes);
582
- bool is_spider_node_visited(const NodeId& id) const;
583
- void mark_spider_node_visited(const NodeId& id);
584
- void cleanup_spider_state();
585
- void cleanup_stale_spider_transactions();
586
- void mark_spider_transaction(const std::string& transaction_id);
587
- bool is_spider_transaction(const std::string& transaction_id); // Also removes if found
588
- void mark_spider_contacted_ip(const std::string& ip);
589
- bool is_spider_contacted_ip(const std::string& ip) const;
590
- #endif // RATS_SEARCH_FEATURES
591
-
592
- // Helper functions
593
- void network_loop();
594
- void maintenance_loop();
595
- void handle_message(const std::vector<uint8_t>& data, const Peer& sender);
596
-
597
-
598
-
599
- // KRPC protocol handlers
600
- void handle_krpc_message(const KrpcMessage& message, const Peer& sender);
601
- void handle_krpc_ping(const KrpcMessage& message, const Peer& sender);
602
- void handle_krpc_find_node(const KrpcMessage& message, const Peer& sender);
603
- void handle_krpc_get_peers(const KrpcMessage& message, const Peer& sender);
604
- void handle_krpc_announce_peer(const KrpcMessage& message, const Peer& sender);
605
- void handle_krpc_response(const KrpcMessage& message, const Peer& sender);
606
- void handle_krpc_error(const KrpcMessage& message, const Peer& sender);
607
-
608
- // KRPC protocol sending
609
- bool send_krpc_message(const KrpcMessage& message, const Peer& peer);
610
- void send_krpc_ping(const Peer& peer);
611
- void send_krpc_find_node(const Peer& peer, const NodeId& target);
612
- void send_krpc_get_peers(const Peer& peer, const InfoHash& info_hash);
613
- void send_krpc_announce_peer(const Peer& peer, const InfoHash& info_hash, uint16_t port, const std::string& token, bool implied_port = false);
614
-
615
- void add_node(const DhtNode& node, bool confirmed = true, bool no_verify = false);
616
- std::vector<DhtNode> find_closest_nodes(const NodeId& target, size_t count = K_BUCKET_SIZE);
617
- std::vector<DhtNode> find_closest_nodes_unlocked(const NodeId& target, size_t count = K_BUCKET_SIZE);
618
- int get_bucket_index(const NodeId& id);
619
-
620
- NodeId generate_node_id();
621
- // BEP 42 internals
622
- static bool is_public_address(const std::string& ip);
623
- void rebuild_routing_table_unlocked(); // re-bucket all nodes after node_id_ changed (routing_table_mutex_ held)
624
- void maybe_update_external_ip(const std::string& reported_ip, const Peer& responder);
625
- NodeId xor_distance(const NodeId& a, const NodeId& b);
626
- bool is_closer(const NodeId& a, const NodeId& b, const NodeId& target);
627
-
628
- /**
629
- * Generate a "neighbor" node ID that appears close to the target
630
- * Spider mode optimization: first 10 bytes from target, last 10 bytes from our ID
631
- * This makes other nodes think we're close to any target they query
632
- * @param target The target node ID to appear close to
633
- * @return A node ID that XOR-distance wise appears close to target
634
- */
635
- NodeId neighbor_id(const NodeId& target) const;
636
-
637
-
638
- // BEP 5 write tokens: bound to the querier address + info_hash and authenticated with a rotating
639
- // secret. generate_token is called when answering get_peers; verify_token gates announce_peer.
640
- std::string generate_token(const Peer& peer, const InfoHash& info_hash);
641
- bool verify_token(const Peer& peer, const InfoHash& info_hash, const std::string& token);
642
- // Computes SHA1(secret || peer.ip || info_hash) as a hex digest. Port is intentionally excluded
643
- // (a NAT may present a different source port on the subsequent announce).
644
- std::string compute_token_with_secret(const Peer& peer, const InfoHash& info_hash,
645
- const std::array<uint8_t, 16>& secret) const;
646
- // Rotates the token secret if older than TOKEN_SECRET_ROTATION_MINUTES. Caller holds token_secret_mutex_.
647
- void maybe_rotate_token_secret_unlocked();
648
-
649
-
650
-
651
- void cleanup_stale_nodes();
652
- void refresh_buckets();
653
- void print_statistics();
654
-
655
- // Pending search management
656
- void cleanup_stale_searches();
657
- void cleanup_timed_out_search_requests();
658
- void cleanup_search_node_states();
659
- void handle_get_peers_response_for_search(const std::string& transaction_id, const Peer& responder, const std::vector<Peer>& peers);
660
- void handle_get_peers_response_with_nodes(const std::string& transaction_id, const Peer& responder, const std::vector<KrpcNode>& nodes);
661
- void handle_get_peers_empty_response(const std::string& transaction_id, const Peer& responder);
662
- void save_write_token(PendingSearch& search, const NodeId& node_id, const std::string& token);
663
- bool add_search_requests(PendingSearch& search, DeferredCallbacks& deferred);
664
- void add_node_to_search(PendingSearch& search, const DhtNode& node);
665
- void send_announce_to_closest_nodes(PendingSearch& search);
666
-
667
- // Peer announcement storage management
668
- void store_announced_peer(const InfoHash& info_hash, const Peer& peer);
669
- std::vector<Peer> get_announced_peers(const InfoHash& info_hash);
670
- void cleanup_stale_announced_peers();
671
-
672
- // Ping-before-replace eviction management
673
- void initiate_ping_verification(const DhtNode& candidate_node, const DhtNode& old_node, int bucket_index);
674
- void handle_ping_verification_response(const std::string& transaction_id, const NodeId& responder_id, const Peer& responder);
675
- void cleanup_stale_ping_verifications();
676
- bool perform_replacement(const DhtNode& candidate_node, const DhtNode& node_to_replace, int bucket_index);
677
-
678
- // Conversion utilities
679
- static KrpcNode dht_node_to_krpc_node(const DhtNode& node);
680
- static DhtNode krpc_node_to_dht_node(const KrpcNode& node);
681
- static std::vector<KrpcNode> dht_nodes_to_krpc_nodes(const std::vector<DhtNode>& nodes);
682
- static std::vector<DhtNode> krpc_nodes_to_dht_nodes(const std::vector<KrpcNode>& nodes);
683
- };
684
-
685
- /**
686
- * Utility functions
687
- */
688
-
689
- /**
690
- * Convert string to NodeId
691
- * @param str The string to convert (must be 20 bytes)
692
- * @return NodeId
693
- */
694
- NodeId string_to_node_id(const std::string& str);
695
-
696
- /**
697
- * Convert NodeId to string
698
- * @param id The NodeId to convert
699
- * @return String representation
700
- */
701
- std::string node_id_to_string(const NodeId& id);
702
-
703
- /**
704
- * Convert hex string to NodeId
705
- * @param hex The hex string to convert (must be 40 characters)
706
- * @return NodeId
707
- */
708
- NodeId hex_to_node_id(const std::string& hex);
709
-
710
- /**
711
- * Convert NodeId to hex string
712
- * @param id The NodeId to convert
713
- * @return Hex string representation
714
- */
715
- std::string node_id_to_hex(const NodeId& id);
716
-
717
- } // namespace librats