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,2324 +0,0 @@
1
- #pragma once
2
-
3
- #include "socket.h"
4
- #include "dht.h"
5
- #include "mdns.h"
6
- #include "logger.h"
7
- #include "threadmanager.h"
8
- #include "gossipsub.h" // For ValidationResult enum and GossipSub types
9
- #include "file_transfer.h" // File transfer functionality
10
- #include "noise.h" // Noise Protocol encryption
11
- #include "ice.h" // ICE-lite NAT traversal
12
- #include "upnp.h" // UPnP IGD automatic port forwarding
13
- #include "natpmp.h" // NAT-PMP automatic port forwarding
14
- #include "io_poller.h" // Platform-optimal I/O multiplexing
15
- #include "receive_buffer.h" // Efficient receive buffer for async I/O
16
- #include "chained_send_buffer.h" // Zero-copy chained send buffer
17
- #ifdef RATS_STORAGE
18
- #include "storage.h" // Distributed storage functionality
19
- #endif
20
- #ifdef RATS_SEARCH_FEATURES
21
- #include "bittorrent.h" // BitTorrent functionality (optional, requires RATS_SEARCH_FEATURES)
22
- #endif
23
- #include "json.hpp" // nlohmann::json
24
- #include <string>
25
- #include <functional>
26
- #include <thread>
27
- #include <vector>
28
- #include <mutex>
29
- #include <atomic>
30
- #include <unordered_map>
31
- #include <memory>
32
- #include <chrono>
33
- #include <unordered_set>
34
- #include <cstdint>
35
- #include <cstring>
36
- #include <optional>
37
- #include "rats_export.h"
38
-
39
- namespace librats {
40
-
41
- // Detects host network configuration changes (defined in network_monitor.h).
42
- // Forward-declared here; only used via unique_ptr, so RatsClient's destructor
43
- // (defined in librats.cpp, which includes network_monitor.h) sees the full type.
44
- class NetworkMonitor;
45
-
46
- /**
47
- * PeerIOContext - Per-peer async I/O buffers and framing state
48
- *
49
- * Used by the single-threaded IO loop for non-blocking message framing:
50
- * recv_buffer – incoming bytes from recv(); frames parsed incrementally
51
- * send_buffer – outgoing frames queued for non-blocking send()
52
- * noise_hs – transient Noise XX handshake state (only during NOISE_PENDING)
53
- * noise_step – current step in the 3-message XX pattern
54
- */
55
- struct PeerIOContext {
56
- ReceiveBuffer recv_buffer{8192};
57
- ChainedSendBuffer send_buffer;
58
-
59
- // Async Noise handshake (only valid while handshake_state == NOISE_PENDING)
60
- std::unique_ptr<rats::NoiseHandshakeState> noise_hs;
61
- int noise_step = 0; // XX pattern: 0→initial, advances per message
62
- };
63
-
64
- /**
65
- * RatsPeer struct - comprehensive information about a connected rats peer
66
- */
67
- struct RatsPeer {
68
- std::string peer_id; // Unique hash ID for the peer
69
- std::string ip; // IP address
70
- uint16_t port; // Port number
71
- socket_t socket; // Socket handle
72
- std::string normalized_address; // Normalized address for duplicate detection (ip:port)
73
- std::chrono::steady_clock::time_point connected_at; // Connection timestamp
74
- bool is_outgoing; // True if we initiated the connection, false if incoming
75
-
76
- // Handshake-related fields
77
- enum class HandshakeState {
78
- PENDING, // Handshake not started
79
- SENT, // Handshake sent, waiting for response
80
- NOISE_PENDING, // Rats handshake done, Noise handshake in progress
81
- COMPLETED, // Handshake completed successfully (including Noise if enabled)
82
- FAILED // Handshake failed
83
- };
84
-
85
- HandshakeState handshake_state; // Current handshake state
86
- std::string version; // Protocol version of remote peer
87
- std::chrono::steady_clock::time_point handshake_start_time; // When handshake started
88
-
89
- // Encryption-related fields
90
- bool encryption_enabled; // Whether encryption is enabled for this peer
91
- bool noise_handshake_completed; // Whether noise handshake is completed
92
- std::shared_ptr<rats::NoiseCipherState> send_cipher; // Cipher for sending encrypted data
93
- std::shared_ptr<rats::NoiseCipherState> recv_cipher; // Cipher for receiving encrypted data
94
- std::vector<uint8_t> remote_static_key; // Remote peer's static public key (for identity verification)
95
-
96
- // Async I/O context (per-peer buffers for non-blocking I/O)
97
- PeerIOContext io_;
98
-
99
- RatsPeer() : handshake_state(HandshakeState::PENDING),
100
- encryption_enabled(false),
101
- noise_handshake_completed(false) {
102
- connected_at = std::chrono::steady_clock::now();
103
- handshake_start_time = connected_at;
104
- }
105
-
106
- RatsPeer(const std::string& id, const std::string& peer_ip, uint16_t peer_port,
107
- socket_t sock, const std::string& norm_addr, bool outgoing)
108
- : peer_id(id), ip(peer_ip), port(peer_port), socket(sock),
109
- normalized_address(norm_addr), is_outgoing(outgoing),
110
- handshake_state(HandshakeState::PENDING),
111
- encryption_enabled(false),
112
- noise_handshake_completed(false) {
113
- connected_at = std::chrono::steady_clock::now();
114
- handshake_start_time = connected_at;
115
- }
116
-
117
- // Custom copy: copies all fields except io_ (non-copyable due to unique_ptr).
118
- // Copies are used for snapshots passed to callbacks – they never need the IO context.
119
- RatsPeer(const RatsPeer& o)
120
- : peer_id(o.peer_id), ip(o.ip), port(o.port), socket(o.socket),
121
- normalized_address(o.normalized_address), connected_at(o.connected_at),
122
- is_outgoing(o.is_outgoing), handshake_state(o.handshake_state),
123
- version(o.version), handshake_start_time(o.handshake_start_time),
124
- encryption_enabled(o.encryption_enabled),
125
- noise_handshake_completed(o.noise_handshake_completed),
126
- send_cipher(o.send_cipher), recv_cipher(o.recv_cipher),
127
- remote_static_key(o.remote_static_key)
128
- /* io_ default-constructed (fresh, empty) */ {}
129
-
130
- RatsPeer& operator=(const RatsPeer& o) {
131
- if (this != &o) {
132
- peer_id = o.peer_id;
133
- ip = o.ip;
134
- port = o.port;
135
- socket = o.socket;
136
- normalized_address = o.normalized_address;
137
- connected_at = o.connected_at;
138
- is_outgoing = o.is_outgoing;
139
- handshake_state = o.handshake_state;
140
- version = o.version;
141
- handshake_start_time = o.handshake_start_time;
142
- encryption_enabled = o.encryption_enabled;
143
- noise_handshake_completed = o.noise_handshake_completed;
144
- send_cipher = o.send_cipher;
145
- recv_cipher = o.recv_cipher;
146
- remote_static_key = o.remote_static_key;
147
- // io_ left unchanged in the destination (no copy)
148
- }
149
- return *this;
150
- }
151
-
152
- // Default move operations are fine
153
- RatsPeer(RatsPeer&&) = default;
154
- RatsPeer& operator=(RatsPeer&&) = default;
155
-
156
- // Check if peer has completed Noise handshake and is ready for encrypted communication
157
- bool is_noise_encrypted() const {
158
- return noise_handshake_completed && send_cipher && recv_cipher;
159
- }
160
-
161
- // Helper methods
162
- bool is_handshake_completed() const { return handshake_state == HandshakeState::COMPLETED; }
163
- bool is_handshake_failed() const { return handshake_state == HandshakeState::FAILED; }
164
- };
165
-
166
- /**
167
- * ReconnectConfig - Configuration for automatic peer reconnection
168
- */
169
- struct ReconnectConfig {
170
- int max_attempts = 3; // Maximum number of reconnection attempts
171
- std::vector<int> retry_intervals_seconds = {5, 30, 120}; // Intervals between attempts (5s, 30s, 2min)
172
- int stable_connection_threshold_seconds = 60; // Connection duration to be considered "stable" (1 minute)
173
- int stable_first_retry_seconds = 2; // First retry interval for stable peers (faster)
174
- bool enabled = true; // Whether auto-reconnection is enabled
175
- };
176
-
177
- /**
178
- * ReconnectInfo - Information about a peer pending reconnection
179
- */
180
- struct ReconnectInfo {
181
- std::string peer_id; // Peer ID for identification
182
- std::string ip; // IP address to reconnect to
183
- uint16_t port; // Port number
184
- int attempt_count; // Current number of reconnection attempts
185
- std::chrono::steady_clock::time_point next_attempt_time; // When to attempt next reconnection
186
- std::chrono::milliseconds connection_duration; // How long the peer was connected before disconnect
187
- bool is_stable; // Whether this was a "stable" connection
188
-
189
- ReconnectInfo() : port(0), attempt_count(0), connection_duration(0), is_stable(false) {
190
- next_attempt_time = std::chrono::steady_clock::now();
191
- }
192
-
193
- ReconnectInfo(const std::string& id, const std::string& peer_ip, uint16_t peer_port,
194
- std::chrono::milliseconds duration, bool stable)
195
- : peer_id(id), ip(peer_ip), port(peer_port), attempt_count(0),
196
- connection_duration(duration), is_stable(stable) {
197
- next_attempt_time = std::chrono::steady_clock::now();
198
- }
199
- };
200
-
201
- /**
202
- * Message data types for librats message headers
203
- */
204
- enum class MessageDataType : uint8_t {
205
- BINARY = 0x01, // Raw binary data
206
- STRING = 0x02, // UTF-8 string data
207
- JSON = 0x03 // JSON formatted data
208
- };
209
-
210
- /**
211
- * Message header structure for librats messages
212
- * Fixed 8-byte header format:
213
- * [0-3]: Magic number "RATS" (4 bytes)
214
- * [4]: Message data type (1 byte)
215
- * [5-7]: Reserved for future use (3 bytes)
216
- */
217
- struct MessageHeader {
218
- static constexpr uint32_t MAGIC_NUMBER = 0x52415453; // "RATS" in ASCII
219
- static constexpr size_t HEADER_SIZE = 8;
220
-
221
- uint32_t magic; // Magic number for validation
222
- MessageDataType type; // Message data type
223
- uint8_t reserved[3]; // Reserved bytes for future use
224
-
225
- MessageHeader(MessageDataType data_type) : magic(MAGIC_NUMBER), type(data_type) {
226
- reserved[0] = reserved[1] = reserved[2] = 0;
227
- }
228
-
229
- MessageHeader() : magic(MAGIC_NUMBER), type(MessageDataType::BINARY) {
230
- reserved[0] = reserved[1] = reserved[2] = 0;
231
- }
232
-
233
- // Serialize header to bytes
234
- std::vector<uint8_t> serialize() const {
235
- std::vector<uint8_t> data(HEADER_SIZE);
236
- uint32_t network_magic = htonl(magic);
237
- memcpy(data.data(), &network_magic, 4);
238
- data[4] = static_cast<uint8_t>(type);
239
- data[5] = reserved[0];
240
- data[6] = reserved[1];
241
- data[7] = reserved[2];
242
- return data;
243
- }
244
-
245
- // Deserialize header from bytes
246
- static bool deserialize(const std::vector<uint8_t>& data, MessageHeader& header) {
247
- if (data.size() < HEADER_SIZE) {
248
- return false;
249
- }
250
-
251
- uint32_t network_magic;
252
- memcpy(&network_magic, data.data(), 4);
253
- header.magic = ntohl(network_magic);
254
-
255
- if (header.magic != MAGIC_NUMBER) {
256
- return false;
257
- }
258
-
259
- header.type = static_cast<MessageDataType>(data[4]);
260
- header.reserved[0] = data[5];
261
- header.reserved[1] = data[6];
262
- header.reserved[2] = data[7];
263
-
264
- return true;
265
- }
266
-
267
- // Validate data type
268
- bool is_valid_type() const {
269
- return type == MessageDataType::BINARY ||
270
- type == MessageDataType::STRING ||
271
- type == MessageDataType::JSON;
272
- }
273
- };
274
-
275
- /**
276
- * RatsClient - Core peer-to-peer networking client
277
- */
278
- class RATS_API RatsClient : public ThreadManager {
279
- public:
280
- // =========================================================================
281
- // Type Definitions and Callbacks
282
- // =========================================================================
283
- using ConnectionCallback = std::function<void(socket_t, const std::string&)>;
284
- using BinaryDataCallback = std::function<void(socket_t, const std::string&, const std::vector<uint8_t>&)>;
285
- using StringDataCallback = std::function<void(socket_t, const std::string&, const std::string&)>;
286
- using JsonDataCallback = std::function<void(socket_t, const std::string&, const nlohmann::json&)>;
287
- using DisconnectCallback = std::function<void(socket_t, const std::string&)>;
288
- using MessageCallback = std::function<void(const std::string&, const nlohmann::json&)>;
289
- using SendCallback = std::function<void(bool, const std::string&)>;
290
- // Fired when the host's network configuration changes (interface up/down, IP
291
- // added/removed, default route change). The argument is the new full list of
292
- // local interface addresses. See on_network_changed().
293
- using NetworkChangeCallback = std::function<void(const std::vector<std::string>& local_addresses)>;
294
-
295
- // =========================================================================
296
- // Constructor and Destructor
297
- // =========================================================================
298
-
299
- /**
300
- * Constructor
301
- * @param listen_port Port to listen on for incoming connections
302
- * @param max_peers Maximum number of concurrent peers (default: 10)
303
- * @param bind_address Interface IP address to bind to (empty for all interfaces)
304
- */
305
- RatsClient(int listen_port, int max_peers = 10, const std::string& bind_address = "");
306
-
307
- /**
308
- * Destructor
309
- */
310
- ~RatsClient();
311
-
312
- // =========================================================================
313
- // Core Lifecycle Management
314
- // =========================================================================
315
-
316
- /**
317
- * Start the RatsClient and begin listening for connections
318
- * @return true if successful, false otherwise
319
- */
320
- bool start();
321
-
322
- /**
323
- * Stop the RatsClient and close all connections
324
- */
325
- void stop();
326
-
327
- /**
328
- * Shutdown all background threads
329
- */
330
- void shutdown_all_threads();
331
-
332
- /**
333
- * Check if the client is currently running
334
- * @return true if running, false otherwise
335
- */
336
- bool is_running() const;
337
-
338
- // =========================================================================
339
- // Utility Methods
340
- // =========================================================================
341
-
342
- int get_listen_port() const;
343
-
344
- /**
345
- * Get the bind address being used
346
- * @return Bind address (empty string if binding to all interfaces)
347
- */
348
- std::string get_bind_address() const;
349
-
350
- // =========================================================================
351
- // Connection Management
352
- // =========================================================================
353
-
354
- /**
355
- * Connect to a peer via direct TCP connection
356
- * @param host Target host/IP address
357
- * @param port Target port
358
- * @return true if connection initiated successfully
359
- */
360
- bool connect_to_peer(const std::string& host, int port);
361
-
362
- /**
363
- * Disconnect from a specific peer
364
- * @param socket Peer socket to disconnect
365
- */
366
- void disconnect_peer(socket_t socket);
367
-
368
- /**
369
- * Disconnect from a peer by peer_id (preferred)
370
- * @param peer_id Peer ID to disconnect
371
- */
372
- void disconnect_peer_by_id(const std::string& peer_id);
373
-
374
- // =========================================================================
375
- // Data Transmission Methods
376
- // =========================================================================
377
-
378
- // Send to specific peer by socket
379
- /**
380
- * Send binary data to a specific peer (primary method)
381
- * @param socket Target peer socket
382
- * @param data Binary data to send
383
- * @param message_type Type of message data (BINARY, STRING, JSON)
384
- * @return true if sent successfully
385
- */
386
- bool send_binary_to_peer(socket_t socket, const std::vector<uint8_t>& data, MessageDataType message_type = MessageDataType::BINARY);
387
-
388
- /**
389
- * Send string data to a specific peer
390
- * @param socket Target peer socket
391
- * @param data String data to send
392
- * @return true if sent successfully
393
- */
394
- bool send_string_to_peer(socket_t socket, const std::string& data);
395
-
396
- /**
397
- * Send JSON data to a specific peer
398
- * @param socket Target peer socket
399
- * @param data JSON data to send
400
- * @return true if sent successfully
401
- */
402
- bool send_json_to_peer(socket_t socket, const nlohmann::json& data);
403
-
404
- // Send to specific peer by ID
405
- /**
406
- * Send binary data to a peer by peer_id (preferred)
407
- * @param peer_id Target peer ID
408
- * @param data Binary data to send
409
- * @param message_type Type of message data (BINARY, STRING, JSON)
410
- * @return true if sent successfully
411
- */
412
- bool send_binary_to_peer_id(const std::string& peer_id, const std::vector<uint8_t>& data, MessageDataType message_type = MessageDataType::BINARY);
413
-
414
- /**
415
- * Send string data to a peer by peer_id (preferred)
416
- * @param peer_id Target peer ID
417
- * @param data String data to send
418
- * @return true if sent successfully
419
- */
420
- bool send_string_to_peer_id(const std::string& peer_id, const std::string& data);
421
-
422
- /**
423
- * Send JSON data to a peer by peer_id (preferred)
424
- * @param peer_id Target peer ID
425
- * @param data JSON data to send
426
- * @return true if sent successfully
427
- */
428
- bool send_json_to_peer_id(const std::string& peer_id, const nlohmann::json& data);
429
-
430
- // Broadcast to all peers
431
- /**
432
- * Broadcast binary data to all connected peers (primary method)
433
- * @param data Binary data to broadcast
434
- * @param message_type Type of message data (BINARY, STRING, JSON)
435
- * @return Number of peers the data was sent to
436
- */
437
- int broadcast_binary_to_peers(const std::vector<uint8_t>& data, MessageDataType message_type = MessageDataType::BINARY);
438
-
439
- /**
440
- * Broadcast string data to all connected peers
441
- * @param data String data to broadcast
442
- * @return Number of peers the data was sent to
443
- */
444
- int broadcast_string_to_peers(const std::string& data);
445
-
446
- /**
447
- * Broadcast JSON data to all connected peers
448
- * @param data JSON data to broadcast
449
- * @return Number of peers the data was sent to
450
- */
451
- int broadcast_json_to_peers(const nlohmann::json& data);
452
-
453
- // =========================================================================
454
- // Peer Information and Management
455
- // =========================================================================
456
-
457
- /**
458
- * Get the number of currently connected peers
459
- * @return Number of connected peers
460
- */
461
- int get_peer_count() const;
462
-
463
- /**
464
- * Get peer_id for a peer by socket (preferred)
465
- * @param socket Peer socket
466
- * @return Peer ID or empty string if not found
467
- */
468
- std::string get_peer_id(socket_t socket) const;
469
-
470
- /**
471
- * Get socket for a peer by peer_id (preferred)
472
- * @param peer_id Peer ID
473
- * @return Peer socket or INVALID_SOCKET_VALUE if not found
474
- */
475
- socket_t get_peer_socket_by_id(const std::string& peer_id) const;
476
-
477
- /**
478
- * Get our own peer ID
479
- * @return Our persistent peer ID
480
- */
481
- std::string get_our_peer_id() const;
482
-
483
- /**
484
- * Get all connected peers
485
- * @return Vector of RatsPeer objects
486
- */
487
- std::vector<RatsPeer> get_all_peers() const;
488
-
489
- /**
490
- * Get all peers that have completed handshake
491
- * @return Vector of RatsPeer objects with completed handshake
492
- */
493
- std::vector<RatsPeer> get_validated_peers() const;
494
-
495
- /**
496
- * Get peer information by peer ID
497
- * @param peer_id The peer ID to look up
498
- * @return Copy of RatsPeer object, or std::nullopt if not found
499
- */
500
- std::optional<RatsPeer> get_peer_by_id(const std::string& peer_id) const;
501
-
502
- /**
503
- * Get peer information by socket
504
- * @param socket The socket handle to look up
505
- * @return Copy of RatsPeer object, or std::nullopt if not found
506
- */
507
- std::optional<RatsPeer> get_peer_by_socket(socket_t socket) const;
508
-
509
- /**
510
- * Get maximum number of peers
511
- * @return Maximum peer count
512
- */
513
- int get_max_peers() const;
514
-
515
- /**
516
- * Set maximum number of peers
517
- * @param max_peers New maximum peer count
518
- */
519
- void set_max_peers(int max_peers);
520
-
521
- /**
522
- * Check if peer limit has been reached
523
- * @return true if at limit, false otherwise
524
- */
525
- bool is_peer_limit_reached() const;
526
-
527
- // =========================================================================
528
- // Automatic Reconnection
529
- // =========================================================================
530
-
531
- /**
532
- * Enable or disable automatic reconnection to disconnected peers
533
- * @param enabled Whether auto-reconnection should be enabled
534
- */
535
- void set_reconnect_enabled(bool enabled);
536
-
537
- /**
538
- * Check if automatic reconnection is enabled
539
- * @return true if auto-reconnection is enabled
540
- */
541
- bool is_reconnect_enabled() const;
542
-
543
- /**
544
- * Set reconnection configuration
545
- * @param config Reconnection configuration settings
546
- */
547
- void set_reconnect_config(const ReconnectConfig& config);
548
-
549
- /**
550
- * Get current reconnection configuration
551
- * @return Copy of current reconnection configuration
552
- */
553
- ReconnectConfig get_reconnect_config() const;
554
-
555
- /**
556
- * Get the number of peers pending reconnection
557
- * @return Number of peers in reconnection queue
558
- */
559
- size_t get_reconnect_queue_size() const;
560
-
561
- /**
562
- * Clear all pending reconnection attempts
563
- */
564
- void clear_reconnect_queue();
565
-
566
- /**
567
- * Get information about peers pending reconnection
568
- * @return Vector of ReconnectInfo for all pending reconnections
569
- */
570
- std::vector<ReconnectInfo> get_reconnect_queue() const;
571
-
572
- // =========================================================================
573
- // Callback Registration
574
- // =========================================================================
575
-
576
- /**
577
- * Set connection callback (called when a new peer connects)
578
- * @param callback Function to call on new connections
579
- */
580
- void set_connection_callback(ConnectionCallback callback);
581
-
582
- /**
583
- * Set binary data callback (called when binary data is received)
584
- * @param callback Function to call when binary data is received
585
- */
586
- void set_binary_data_callback(BinaryDataCallback callback);
587
-
588
- /**
589
- * Set string data callback (called when string data is received)
590
- * @param callback Function to call when string data is received
591
- */
592
- void set_string_data_callback(StringDataCallback callback);
593
-
594
- /**
595
- * Set JSON data callback (called when JSON data is received)
596
- * @param callback Function to call when JSON data is received
597
- */
598
- void set_json_data_callback(JsonDataCallback callback);
599
-
600
- /**
601
- * Set disconnect callback (called when a peer disconnects)
602
- * @param callback Function to call on disconnections
603
- */
604
- void set_disconnect_callback(DisconnectCallback callback);
605
-
606
- // =========================================================================
607
- // Peer Discovery Methods
608
- // =========================================================================
609
-
610
- // DHT Discovery
611
- /**
612
- * Start DHT discovery on specified port
613
- * @param dht_port Port for DHT communication (default: 6881)
614
- * @return true if started successfully
615
- */
616
- bool start_dht_discovery(int dht_port = 6881);
617
-
618
- /**
619
- * Stop DHT discovery
620
- */
621
- void stop_dht_discovery();
622
-
623
- /**
624
- * Find peers by content hash using DHT
625
- * @param content_hash Hash to search for (40-character hex string)
626
- * @param callback Function to call with discovered peers
627
- * @return true if search initiated successfully
628
- */
629
- bool find_peers_by_hash(const std::string& content_hash,
630
- std::function<void(const std::vector<std::string>&)> callback);
631
-
632
- /**
633
- * Announce our presence for a content hash with optional peer discovery callback
634
- * If callback is provided, peers discovered during DHT traversal will be returned through it
635
- * @param content_hash Hash to announce for (40-character hex string)
636
- * @param port Port to announce (default: our listen port)
637
- * @param callback Optional function to call with discovered peers during traversal
638
- * @return true if announced successfully
639
- */
640
- bool announce_for_hash(const std::string& content_hash, uint16_t port = 0,
641
- std::function<void(const std::vector<std::string>&)> callback = nullptr);
642
-
643
- /**
644
- * Check if DHT is currently running
645
- * @return true if DHT is running
646
- */
647
- bool is_dht_running() const;
648
-
649
- /**
650
- * Get the size of the DHT routing table
651
- * @return Number of nodes in routing table
652
- */
653
- size_t get_dht_routing_table_size() const;
654
-
655
- // mDNS Discovery
656
- /**
657
- * Start mDNS service discovery and announcement
658
- * @param service_instance_name Service instance name (optional)
659
- * @param txt_records Additional TXT records for service announcement
660
- * @return true if started successfully
661
- */
662
- bool start_mdns_discovery(const std::string& service_instance_name = "",
663
- const std::map<std::string, std::string>& txt_records = {});
664
-
665
- /**
666
- * Stop mDNS discovery
667
- */
668
- void stop_mdns_discovery();
669
-
670
- /**
671
- * Check if mDNS is currently running
672
- * @return true if mDNS is running
673
- */
674
- bool is_mdns_running() const;
675
-
676
- /**
677
- * Set mDNS service discovery callback
678
- * @param callback Function to call when services are discovered
679
- */
680
- void set_mdns_callback(std::function<void(const std::string&, int, const std::string&)> callback);
681
-
682
- /**
683
- * Get recently discovered mDNS services
684
- * @return Vector of discovered services
685
- */
686
- std::vector<MdnsService> get_mdns_services() const;
687
-
688
- /**
689
- * Manually query for mDNS services
690
- * @return true if query sent successfully
691
- */
692
- bool query_mdns_services();
693
-
694
- // Automatic Discovery
695
- /**
696
- * Start automatic peer discovery
697
- */
698
- void start_automatic_peer_discovery();
699
-
700
- /**
701
- * Stop automatic peer discovery
702
- */
703
- void stop_automatic_peer_discovery();
704
-
705
- /**
706
- * Check if automatic discovery is running
707
- * @return true if automatic discovery is running
708
- */
709
- bool is_automatic_discovery_running() const;
710
-
711
- /**
712
- * Calculate discovery interval based on current peer count
713
- * Uses graduated scaling: more aggressive when fewer peers, less aggressive when nearly full
714
- * @return Discovery interval in seconds
715
- */
716
- std::chrono::seconds calculate_discovery_interval() const;
717
-
718
- /**
719
- * Get the discovery hash for current protocol configuration
720
- * @return Discovery hash based on current protocol name and version
721
- */
722
- std::string get_discovery_hash() const;
723
-
724
- /**
725
- * Get the well-known RATS peer discovery hash
726
- * @return Standard RATS discovery hash
727
- */
728
- static std::string get_rats_peer_discovery_hash();
729
-
730
- /**
731
- * Add an IP address to the ignore list (for blocking connections to self)
732
- * @param ip_address IP address to ignore
733
- */
734
- void add_ignored_address(const std::string& ip_address);
735
-
736
- // =========================================================================
737
- // Protocol Configuration
738
- // =========================================================================
739
-
740
- /**
741
- * Set custom protocol name for handshakes and DHT discovery
742
- * @param protocol_name Custom protocol name (default: "rats")
743
- */
744
- void set_protocol_name(const std::string& protocol_name);
745
-
746
- /**
747
- * Set custom protocol version for handshakes
748
- * @param protocol_version Custom protocol version (default: "1.0")
749
- */
750
- void set_protocol_version(const std::string& protocol_version);
751
-
752
- /**
753
- * Get current protocol name
754
- * @return Current protocol name
755
- */
756
- std::string get_protocol_name() const;
757
-
758
- /**
759
- * Get current protocol version
760
- * @return Current protocol version
761
- */
762
- std::string get_protocol_version() const;
763
-
764
- // =========================================================================
765
- // Message Exchange API
766
- // =========================================================================
767
-
768
- /**
769
- * Register a persistent message handler
770
- * @param message_type Type of message to handle
771
- * @param callback Function to call when message is received
772
- */
773
- void on(const std::string& message_type, MessageCallback callback);
774
-
775
- /**
776
- * Register a one-time message handler
777
- * @param message_type Type of message to handle
778
- * @param callback Function to call when message is received (once only)
779
- */
780
- void once(const std::string& message_type, MessageCallback callback);
781
-
782
- /**
783
- * Remove all handlers for a message type
784
- * @param message_type Type of message to stop handling
785
- */
786
- void off(const std::string& message_type);
787
-
788
- /**
789
- * Send a message to all peers
790
- * @param message_type Type of message
791
- * @param data Message data
792
- * @param callback Optional callback for send result
793
- */
794
- void send(const std::string& message_type, const nlohmann::json& data, SendCallback callback = nullptr);
795
-
796
- /**
797
- * Send a message to a specific peer
798
- * @param peer_id Target peer ID
799
- * @param message_type Type of message
800
- * @param data Message data
801
- * @param callback Optional callback for send result
802
- */
803
- void send(const std::string& peer_id, const std::string& message_type, const nlohmann::json& data, SendCallback callback = nullptr);
804
-
805
- // =========================================================================
806
- // Encryption Functionality
807
- // =========================================================================
808
-
809
- /**
810
- * Initialize encryption system
811
- * @param enable Whether to enable encryption
812
- * @return true if successful
813
- */
814
- bool initialize_encryption(bool enable);
815
-
816
- /**
817
- * Set encryption enabled/disabled
818
- * @param enabled Whether encryption should be enabled
819
- */
820
- void set_encryption_enabled(bool enabled);
821
-
822
- /**
823
- * Check if encryption is enabled
824
- * @return true if encryption is enabled
825
- */
826
- bool is_encryption_enabled() const;
827
-
828
- /**
829
- * Check if a peer connection is encrypted
830
- * @param peer_id Peer ID to check
831
- * @return true if peer connection is encrypted
832
- */
833
- bool is_peer_encrypted(const std::string& peer_id) const;
834
-
835
- /**
836
- * Set a custom static keypair for Noise Protocol
837
- * If not set, a new keypair is generated automatically
838
- * @param private_key 32-byte private key
839
- * @return true if the keypair was set successfully
840
- */
841
- bool set_noise_static_keypair(const uint8_t private_key[32]);
842
-
843
- /**
844
- * Get our Noise Protocol static public key
845
- * @return 32-byte public key
846
- */
847
- std::vector<uint8_t> get_noise_static_public_key() const;
848
-
849
- /**
850
- * Get the remote peer's Noise static public key
851
- * @param peer_id Peer ID to query
852
- * @return 32-byte public key, or empty vector if not available
853
- */
854
- std::vector<uint8_t> get_peer_noise_public_key(const std::string& peer_id) const;
855
-
856
- /**
857
- * Get the handshake hash for a peer connection (for channel binding)
858
- * @param peer_id Peer ID to query
859
- * @return 32-byte handshake hash, or empty vector if not available
860
- */
861
- std::vector<uint8_t> get_peer_handshake_hash(const std::string& peer_id) const;
862
-
863
- // =========================================================================
864
- // Configuration Persistence
865
- // =========================================================================
866
-
867
- /**
868
- * Load configuration from files
869
- * @return true if successful, false otherwise
870
- */
871
- bool load_configuration();
872
-
873
- /**
874
- * Save configuration to files
875
- * @return true if successful, false otherwise
876
- */
877
- bool save_configuration();
878
-
879
- /**
880
- * Set directory where data files will be stored
881
- * @param directory_path Path to directory (default: current folder)
882
- * @return true if directory is accessible, false otherwise
883
- */
884
- bool set_data_directory(const std::string& directory_path);
885
-
886
- /**
887
- * Get current data directory path
888
- * @return Current data directory path
889
- */
890
- std::string get_data_directory() const;
891
-
892
- /**
893
- * Load saved peers and attempt to reconnect
894
- * @return Number of connection attempts made
895
- */
896
- int load_and_reconnect_peers();
897
-
898
- /**
899
- * Load historical peers from a file
900
- * @return true if successful, false otherwise
901
- */
902
- bool load_historical_peers();
903
-
904
- /**
905
- * Save current peers to a historical file
906
- * @return true if successful, false otherwise
907
- */
908
- bool save_historical_peers();
909
-
910
- /**
911
- * Clear all historical peers
912
- */
913
- void clear_historical_peers();
914
-
915
- /**
916
- * Get all historical peers
917
- * @return Vector of RatsPeer objects
918
- */
919
- std::vector<RatsPeer> get_historical_peers() const;
920
-
921
- // =========================================================================
922
- // Statistics and Information
923
- // =========================================================================
924
-
925
- /**
926
- * Get connection statistics
927
- * @return JSON object with detailed statistics
928
- */
929
- nlohmann::json get_connection_statistics() const;
930
-
931
- // =========================================================================
932
- // GossipSub Functionality
933
- // =========================================================================
934
-
935
- /**
936
- * Get GossipSub instance for publish-subscribe messaging
937
- * @return Reference to GossipSub instance
938
- */
939
- GossipSub& get_gossipsub();
940
-
941
- /**
942
- * Check if GossipSub is available
943
- * @return true if GossipSub is initialized
944
- */
945
- bool is_gossipsub_available() const;
946
-
947
- // Topic Management
948
- /**
949
- * Subscribe to a GossipSub topic
950
- * @param topic Topic name to subscribe to
951
- * @return true if subscription successful
952
- */
953
- bool subscribe_to_topic(const std::string& topic);
954
-
955
- /**
956
- * Unsubscribe from a GossipSub topic
957
- * @param topic Topic name to unsubscribe from
958
- * @return true if unsubscription successful
959
- */
960
- bool unsubscribe_from_topic(const std::string& topic);
961
-
962
- /**
963
- * Check if subscribed to a GossipSub topic
964
- * @param topic Topic name to check
965
- * @return true if subscribed
966
- */
967
- bool is_subscribed_to_topic(const std::string& topic) const;
968
-
969
- /**
970
- * Get list of subscribed GossipSub topics
971
- * @return Vector of topic names
972
- */
973
- std::vector<std::string> get_subscribed_topics() const;
974
-
975
- // Publishing
976
- /**
977
- * Publish a message to a GossipSub topic
978
- * @param topic Topic to publish to
979
- * @param message Message content
980
- * @return true if published successfully
981
- */
982
- bool publish_to_topic(const std::string& topic, const std::string& message);
983
-
984
- /**
985
- * Publish a JSON message to a GossipSub topic
986
- * @param topic Topic to publish to
987
- * @param message JSON message content
988
- * @return true if published successfully
989
- */
990
- bool publish_json_to_topic(const std::string& topic, const nlohmann::json& message);
991
-
992
- // Event Handlers (Unified API)
993
- /**
994
- * Set a message handler for a GossipSub topic using unified event API pattern
995
- * @param topic Topic name
996
- * @param callback Function to call when messages are received (peer_id, topic, message_content)
997
- */
998
- void on_topic_message(const std::string& topic, std::function<void(const std::string&, const std::string&, const std::string&)> callback);
999
-
1000
- /**
1001
- * Set a JSON message handler for a GossipSub topic using unified event API pattern
1002
- * @param topic Topic name
1003
- * @param callback Function to call when JSON messages are received (peer_id, topic, json_message)
1004
- */
1005
- void on_topic_json_message(const std::string& topic, std::function<void(const std::string&, const std::string&, const nlohmann::json&)> callback);
1006
-
1007
- /**
1008
- * Set a peer joined handler for a GossipSub topic using unified event API pattern
1009
- * @param topic Topic name
1010
- * @param callback Function to call when peers join the topic
1011
- */
1012
- void on_topic_peer_joined(const std::string& topic, std::function<void(const std::string&, const std::string&)> callback);
1013
-
1014
- /**
1015
- * Set a peer left handler for a GossipSub topic using unified event API pattern
1016
- * @param topic Topic name
1017
- * @param callback Function to call when peers leave the topic
1018
- */
1019
- void on_topic_peer_left(const std::string& topic, std::function<void(const std::string&, const std::string&)> callback);
1020
-
1021
- /**
1022
- * Set a message validator for a GossipSub topic
1023
- * @param topic Topic name (empty for global validator)
1024
- * @param validator Validation function returning ACCEPT, REJECT, or IGNORE_MSG
1025
- */
1026
- void set_topic_message_validator(const std::string& topic, std::function<ValidationResult(const std::string&, const std::string&, const std::string&)> validator);
1027
-
1028
- /**
1029
- * Remove all event handlers for a GossipSub topic
1030
- * @param topic Topic name
1031
- */
1032
- void off_topic(const std::string& topic);
1033
-
1034
- // Information
1035
- /**
1036
- * Get peers subscribed to a GossipSub topic
1037
- * @param topic Topic name
1038
- * @return Vector of peer IDs
1039
- */
1040
- std::vector<std::string> get_topic_peers(const std::string& topic) const;
1041
-
1042
- /**
1043
- * Get mesh peers for a GossipSub topic
1044
- * @param topic Topic name
1045
- * @return Vector of peer IDs in the mesh
1046
- */
1047
- std::vector<std::string> get_topic_mesh_peers(const std::string& topic) const;
1048
-
1049
- /**
1050
- * Get GossipSub statistics
1051
- * @return JSON object with comprehensive GossipSub statistics
1052
- */
1053
- nlohmann::json get_gossipsub_statistics() const;
1054
-
1055
- /**
1056
- * Check if GossipSub is running
1057
- * @return true if GossipSub service is active
1058
- */
1059
- bool is_gossipsub_running() const;
1060
-
1061
- // =========================================================================
1062
- // Logging Control API
1063
- // =========================================================================
1064
-
1065
- /**
1066
- * Enable or disable console logging
1067
- * When disabled, log messages will not be printed to stdout/stderr
1068
- * File logging (if enabled) will still work
1069
- * @param enabled Whether to enable console logging (default: true)
1070
- */
1071
- void set_console_logging_enabled(bool enabled);
1072
-
1073
- /**
1074
- * Check if console logging is currently enabled
1075
- * @return true if console logging is enabled
1076
- */
1077
- bool is_console_logging_enabled() const;
1078
-
1079
- /**
1080
- * Enable or disable file logging
1081
- * When enabled, logs will be written to "rats.log" by default
1082
- * @param enabled Whether to enable file logging
1083
- */
1084
- void set_logging_enabled(bool enabled);
1085
-
1086
- /**
1087
- * Check if file logging is currently enabled
1088
- * @return true if file logging is enabled
1089
- */
1090
- bool is_logging_enabled() const;
1091
-
1092
- /**
1093
- * Set the log file path
1094
- * @param file_path Path to the log file (default: "rats.log")
1095
- */
1096
- void set_log_file_path(const std::string& file_path);
1097
-
1098
- /**
1099
- * Get the current log file path
1100
- * @return Current log file path
1101
- */
1102
- std::string get_log_file_path() const;
1103
-
1104
- /**
1105
- * Set the minimum log level
1106
- * @param level Minimum log level (DEBUG=0, INFO=1, WARN=2, ERROR=3)
1107
- */
1108
- void set_log_level(LogLevel level);
1109
-
1110
- /**
1111
- * Set the minimum log level using string
1112
- * @param level_str Log level as string ("DEBUG", "INFO", "WARN", "ERROR")
1113
- */
1114
- void set_log_level(const std::string& level_str);
1115
-
1116
- /**
1117
- * Get the current log level
1118
- * @return Current minimum log level
1119
- */
1120
- LogLevel get_log_level() const;
1121
-
1122
- /**
1123
- * Enable or disable colored log output
1124
- * @param enabled Whether to enable colored output
1125
- */
1126
- void set_log_colors_enabled(bool enabled);
1127
-
1128
- /**
1129
- * Check if colored log output is enabled
1130
- * @return true if colors are enabled
1131
- */
1132
- bool is_log_colors_enabled() const;
1133
-
1134
- /**
1135
- * Enable or disable timestamps in log output
1136
- * @param enabled Whether to enable timestamps
1137
- */
1138
- void set_log_timestamps_enabled(bool enabled);
1139
-
1140
- /**
1141
- * Check if timestamps are enabled in log output
1142
- * @return true if timestamps are enabled
1143
- */
1144
- bool is_log_timestamps_enabled() const;
1145
-
1146
- /**
1147
- * Set log file rotation size
1148
- * @param max_size_bytes Maximum size in bytes before log rotation (default: 10MB)
1149
- */
1150
- void set_log_rotation_size(size_t max_size_bytes);
1151
-
1152
- /**
1153
- * Set the number of log files to retain during rotation
1154
- * @param count Number of old log files to keep (default: 5)
1155
- */
1156
- void set_log_retention_count(int count);
1157
-
1158
- /**
1159
- * Enable or disable log rotation on application startup
1160
- * When enabled, the existing log file will be rotated when logging starts,
1161
- * so each application run gets a fresh log file
1162
- * @param enabled Whether to rotate logs on startup (default: false)
1163
- */
1164
- void set_log_rotate_on_startup(bool enabled);
1165
-
1166
- /**
1167
- * Check if log rotation on startup is enabled
1168
- * @return true if rotate on startup is enabled
1169
- */
1170
- bool is_log_rotate_on_startup_enabled() const;
1171
-
1172
- /**
1173
- * Clear/reset the current log file
1174
- */
1175
- void clear_log_file();
1176
-
1177
- // =========================================================================
1178
- // File Transfer API
1179
- // =========================================================================
1180
- //
1181
- // Streams files and directory trees to connected peers. A transfer is
1182
- // offered to the peer, who accepts (choosing a destination) or rejects it.
1183
- // See file_transfer.h for the FileTransferManager that implements it.
1184
-
1185
- /**
1186
- * Get the file transfer manager instance.
1187
- */
1188
- FileTransferManager& get_file_transfer_manager();
1189
-
1190
- /**
1191
- * Check whether the file transfer manager is initialized.
1192
- */
1193
- bool is_file_transfer_available() const;
1194
-
1195
- /**
1196
- * Send a file to a peer.
1197
- * @param peer_id Target peer ID
1198
- * @param file_path Local file to send
1199
- * @param remote_filename Optional name to present to the peer
1200
- * @return Transfer ID, or empty string on immediate failure
1201
- */
1202
- std::string send_file(const std::string& peer_id, const std::string& file_path,
1203
- const std::string& remote_filename = "");
1204
-
1205
- /**
1206
- * Send a directory tree (recursively) to a peer.
1207
- * @param peer_id Target peer ID
1208
- * @param directory_path Local directory to send
1209
- * @param remote_name Optional name to present to the peer
1210
- * @return Transfer ID, or empty string on immediate failure
1211
- */
1212
- std::string send_directory(const std::string& peer_id, const std::string& directory_path,
1213
- const std::string& remote_name = "");
1214
-
1215
- /**
1216
- * Accept an incoming transfer. For a file, local_path is the destination
1217
- * file path; for a directory, it is the destination directory.
1218
- */
1219
- bool accept_file_transfer(const std::string& transfer_id, const std::string& local_path);
1220
-
1221
- /**
1222
- * Reject an incoming transfer.
1223
- */
1224
- bool reject_file_transfer(const std::string& transfer_id, const std::string& reason = "");
1225
-
1226
- /** Pause an active transfer (either direction). */
1227
- bool pause_file_transfer(const std::string& transfer_id);
1228
-
1229
- /** Resume a paused transfer. */
1230
- bool resume_file_transfer(const std::string& transfer_id);
1231
-
1232
- /** Cancel an active or paused transfer. */
1233
- bool cancel_file_transfer(const std::string& transfer_id);
1234
-
1235
- /** Get a progress snapshot, or nullptr if the transfer is unknown. */
1236
- std::shared_ptr<FileTransferProgress> get_file_transfer_progress(const std::string& transfer_id) const;
1237
-
1238
- /** Get progress snapshots for all non-finished transfers. */
1239
- std::vector<std::shared_ptr<FileTransferProgress>> get_active_file_transfers() const;
1240
-
1241
- /** Get aggregate file transfer statistics as JSON. */
1242
- nlohmann::json get_file_transfer_statistics() const;
1243
-
1244
- /** Replace the file transfer configuration. */
1245
- void set_file_transfer_config(const FileTransferConfig& config);
1246
-
1247
- /** Get the current file transfer configuration. */
1248
- FileTransferConfig get_file_transfer_config() const;
1249
-
1250
- /** Set the progress callback (fires for both directions). */
1251
- void on_file_transfer_progress(TransferProgressCallback callback);
1252
-
1253
- /** Set the completion callback (fires once per transfer). */
1254
- void on_file_transfer_completed(TransferCompletedCallback callback);
1255
-
1256
- /**
1257
- * Set the incoming-offer callback. The handler should call
1258
- * accept_file_transfer()/reject_file_transfer(). Without it, offers are
1259
- * auto-rejected.
1260
- */
1261
- void on_file_transfer_request(TransferOfferCallback callback);
1262
-
1263
- // =========================================================================
1264
- // ICE (NAT Traversal) API
1265
- // =========================================================================
1266
-
1267
- /**
1268
- * Get the ICE manager instance
1269
- * @return Reference to the ICE manager
1270
- */
1271
- IceManager& get_ice_manager();
1272
-
1273
- /**
1274
- * Check if ICE is available
1275
- * @return true if ICE manager is initialized
1276
- */
1277
- bool is_ice_available() const;
1278
-
1279
- // Server Configuration
1280
- /**
1281
- * Add a STUN server for NAT traversal
1282
- * @param host STUN server hostname or IP
1283
- * @param port STUN server port (default: 3478)
1284
- */
1285
- void add_stun_server(const std::string& host, uint16_t port = STUN_DEFAULT_PORT);
1286
-
1287
- /**
1288
- * Add a TURN server for relay-based NAT traversal
1289
- * @param host TURN server hostname or IP
1290
- * @param port TURN server port (default: 3478)
1291
- * @param username TURN username
1292
- * @param password TURN password
1293
- */
1294
- void add_turn_server(const std::string& host, uint16_t port,
1295
- const std::string& username, const std::string& password);
1296
-
1297
- /**
1298
- * Clear all ICE (STUN/TURN) servers
1299
- */
1300
- void clear_ice_servers();
1301
-
1302
- // Candidate Gathering
1303
- /**
1304
- * Start gathering ICE candidates
1305
- * This discovers our public address and generates connection candidates
1306
- * @return true if gathering started successfully
1307
- */
1308
- bool gather_ice_candidates();
1309
-
1310
- /**
1311
- * Get our local ICE candidates
1312
- * Call after gathering is complete
1313
- * @return Vector of ICE candidates
1314
- */
1315
- std::vector<IceCandidate> get_ice_candidates() const;
1316
-
1317
- /**
1318
- * Check if ICE candidate gathering is complete
1319
- * @return true if gathering is complete
1320
- */
1321
- bool is_ice_gathering_complete() const;
1322
-
1323
- // Public Address Discovery
1324
- /**
1325
- * Get our public IP address (discovered via STUN)
1326
- * @return Pair of (IP, port) or nullopt if not discovered
1327
- */
1328
- std::optional<std::pair<std::string, uint16_t>> get_public_address() const;
1329
-
1330
- /**
1331
- * Perform a simple STUN binding request to discover public address
1332
- * This is a convenience method that doesn't require full ICE setup
1333
- * @param server STUN server hostname
1334
- * @param port STUN server port (default: 3478)
1335
- * @param timeout_ms Timeout in milliseconds (default: 5000)
1336
- * @return Mapped address or nullopt on failure
1337
- */
1338
- std::optional<StunMappedAddress> discover_public_address(
1339
- const std::string& server = "stun.l.google.com",
1340
- uint16_t port = 19302,
1341
- int timeout_ms = 5000);
1342
-
1343
- // Remote Candidates
1344
- /**
1345
- * Add a remote ICE candidate (received from peer via signaling)
1346
- * @param candidate Remote candidate to add
1347
- */
1348
- void add_remote_ice_candidate(const IceCandidate& candidate);
1349
-
1350
- /**
1351
- * Add remote ICE candidates from SDP attribute lines
1352
- * @param sdp_lines Vector of SDP candidate lines
1353
- */
1354
- void add_remote_ice_candidates_from_sdp(const std::vector<std::string>& sdp_lines);
1355
-
1356
- /**
1357
- * Signal end of remote candidates (trickle ICE complete)
1358
- */
1359
- void end_of_remote_ice_candidates();
1360
-
1361
- // Connectivity
1362
- /**
1363
- * Start ICE connectivity checks
1364
- */
1365
- void start_ice_checks();
1366
-
1367
- /**
1368
- * Get current ICE connection state
1369
- * @return ICE connection state
1370
- */
1371
- IceConnectionState get_ice_connection_state() const;
1372
-
1373
- /**
1374
- * Get ICE gathering state
1375
- * @return ICE gathering state
1376
- */
1377
- IceGatheringState get_ice_gathering_state() const;
1378
-
1379
- /**
1380
- * Check if ICE is connected
1381
- * @return true if ICE connection is established
1382
- */
1383
- bool is_ice_connected() const;
1384
-
1385
- /**
1386
- * Get the selected ICE candidate pair
1387
- * @return Selected candidate pair or nullopt
1388
- */
1389
- std::optional<IceCandidatePair> get_ice_selected_pair() const;
1390
-
1391
- // ICE Event Callbacks
1392
- /**
1393
- * Set callback for ICE candidates gathered
1394
- * @param callback Function called with all candidates when gathering completes
1395
- */
1396
- void on_ice_candidates_gathered(IceCandidatesCallback callback);
1397
-
1398
- /**
1399
- * Set callback for new ICE candidate (trickle ICE)
1400
- * @param callback Function called when each new candidate is discovered
1401
- */
1402
- void on_ice_new_candidate(IceNewCandidateCallback callback);
1403
-
1404
- /**
1405
- * Set callback for ICE gathering state changes
1406
- * @param callback Function called when gathering state changes
1407
- */
1408
- void on_ice_gathering_state_changed(IceGatheringStateCallback callback);
1409
-
1410
- /**
1411
- * Set callback for ICE connection state changes
1412
- * @param callback Function called when connection state changes
1413
- */
1414
- void on_ice_connection_state_changed(IceConnectionStateCallback callback);
1415
-
1416
- /**
1417
- * Set callback for ICE selected pair
1418
- * @param callback Function called when a candidate pair is selected
1419
- */
1420
- void on_ice_selected_pair(IceSelectedPairCallback callback);
1421
-
1422
- // ICE Configuration
1423
- /**
1424
- * Set ICE configuration
1425
- * @param config ICE configuration settings
1426
- */
1427
- void set_ice_config(const IceConfig& config);
1428
-
1429
- /**
1430
- * Get current ICE configuration
1431
- * @return Current ICE configuration
1432
- */
1433
- IceConfig get_ice_config() const;
1434
-
1435
- // ICE Lifecycle
1436
- /**
1437
- * Close ICE manager and release resources
1438
- */
1439
- void close_ice();
1440
-
1441
- /**
1442
- * Restart ICE (re-gather candidates and restart checks)
1443
- */
1444
- void restart_ice();
1445
-
1446
- // =========================================================================
1447
- // Automatic Port Forwarding API (UPnP IGD + NAT-PMP)
1448
- // =========================================================================
1449
- //
1450
- // When enabled (the default), RatsClient asks the home router to forward the
1451
- // TCP listen port on startup, using UPnP and NAT-PMP in parallel (whichever
1452
- // the router supports wins). Mappings are refreshed automatically and removed
1453
- // on stop(). This lets peers behind a NAT accept inbound connections without
1454
- // manual router configuration.
1455
-
1456
- /**
1457
- * Enable or disable automatic port forwarding. If toggled while running, the
1458
- * port mapping backends are started or stopped immediately. The setting is
1459
- * persisted to config.json.
1460
- */
1461
- void set_port_mapping_enabled(bool enabled);
1462
-
1463
- /// Whether automatic port forwarding is currently enabled.
1464
- bool is_port_mapping_enabled() const;
1465
-
1466
- /// Replace the full port mapping configuration (takes effect on next start).
1467
- void set_port_mapping_config(const PortMappingConfig& config);
1468
-
1469
- /// Get the current port mapping configuration.
1470
- PortMappingConfig get_port_mapping_config() const;
1471
-
1472
- /**
1473
- * Request an additional port mapping beyond the automatic listen-port mapping
1474
- * (e.g. a DHT UDP port). Has effect only while port mapping is enabled.
1475
- */
1476
- void add_port_mapping(PortMapProtocol protocol, uint16_t port);
1477
-
1478
- /**
1479
- * Get the public (external) address discovered by the port mapping backends.
1480
- * @return {external_ip, external_port} if a mapping is active, otherwise nullopt
1481
- */
1482
- std::optional<std::pair<std::string, uint16_t>> get_mapped_public_address() const;
1483
-
1484
- /**
1485
- * Register a callback fired whenever a port mapping is established, refreshed,
1486
- * removed or fails (invoked from a backend worker thread).
1487
- */
1488
- void on_port_mapping(PortMapCallback callback);
1489
-
1490
- // =========================================================================
1491
- // Network change detection
1492
- // =========================================================================
1493
- //
1494
- // A long-lived node must notice when the host's connectivity changes (a new
1495
- // interface, an IP added/removed, the default route flipping between Wi-Fi
1496
- // and cellular, dock/undock, VPN up/down, wake-from-sleep) and recover:
1497
- // renew router port mappings, re-discover its public address via STUN, and
1498
- // re-announce to the DHT. Otherwise it keeps advertising a stale endpoint
1499
- // until the next periodic refresh. Enabled by default. Implemented in
1500
- // librats_portmap.cpp on top of the platform-specific NetworkMonitor.
1501
-
1502
- /**
1503
- * Enable or disable automatic reaction to host network changes. Enabled by
1504
- * default. Can be called before or after start(): toggling while running
1505
- * starts/stops the monitor immediately. Not persisted.
1506
- */
1507
- void set_network_change_detection_enabled(bool enabled);
1508
- bool is_network_change_detection_enabled() const;
1509
-
1510
- /**
1511
- * Register a callback fired (debounced) whenever the set of local interface
1512
- * addresses changes. The argument is the new full list of local addresses.
1513
- * Invoked from the monitor's worker thread, so keep the handler quick. This
1514
- * is in addition to — not a replacement for — the built-in recovery
1515
- * (port re-mapping, STUN re-discovery, DHT re-announce).
1516
- */
1517
- void on_network_changed(NetworkChangeCallback callback);
1518
-
1519
- #ifdef RATS_STORAGE
1520
- // =========================================================================
1521
- // Distributed Storage API (requires RATS_STORAGE)
1522
- // =========================================================================
1523
-
1524
- /**
1525
- * Get the storage manager instance
1526
- * @return Reference to the storage manager
1527
- */
1528
- StorageManager& get_storage_manager();
1529
-
1530
- /**
1531
- * Check if storage is available
1532
- * @return true if storage manager is initialized
1533
- */
1534
- bool is_storage_available() const;
1535
-
1536
- // Put Operations
1537
- /**
1538
- * Store a string value
1539
- * @param key Key to store under
1540
- * @param value String value to store
1541
- * @return true if stored successfully
1542
- */
1543
- bool storage_put(const std::string& key, const std::string& value);
1544
-
1545
- /**
1546
- * Store a 64-bit integer value
1547
- * @param key Key to store under
1548
- * @param value Integer value to store
1549
- * @return true if stored successfully
1550
- */
1551
- bool storage_put(const std::string& key, int64_t value);
1552
-
1553
- /**
1554
- * Store a double-precision floating point value
1555
- * @param key Key to store under
1556
- * @param value Double value to store
1557
- * @return true if stored successfully
1558
- */
1559
- bool storage_put(const std::string& key, double value);
1560
-
1561
- /**
1562
- * Store binary data
1563
- * @param key Key to store under
1564
- * @param value Binary data to store
1565
- * @return true if stored successfully
1566
- */
1567
- bool storage_put(const std::string& key, const std::vector<uint8_t>& value);
1568
-
1569
- /**
1570
- * Store a JSON document
1571
- * @param key Key to store under
1572
- * @param value JSON value to store
1573
- * @return true if stored successfully
1574
- */
1575
- bool storage_put_json(const std::string& key, const nlohmann::json& value);
1576
-
1577
- // Get Operations
1578
- /**
1579
- * Get a string value
1580
- * @param key Key to retrieve
1581
- * @return Optional containing value if found and type matches
1582
- */
1583
- std::optional<std::string> storage_get_string(const std::string& key) const;
1584
-
1585
- /**
1586
- * Get a 64-bit integer value
1587
- * @param key Key to retrieve
1588
- * @return Optional containing value if found and type matches
1589
- */
1590
- std::optional<int64_t> storage_get_int(const std::string& key) const;
1591
-
1592
- /**
1593
- * Get a double-precision floating point value
1594
- * @param key Key to retrieve
1595
- * @return Optional containing value if found and type matches
1596
- */
1597
- std::optional<double> storage_get_double(const std::string& key) const;
1598
-
1599
- /**
1600
- * Get binary data
1601
- * @param key Key to retrieve
1602
- * @return Optional containing value if found and type matches
1603
- */
1604
- std::optional<std::vector<uint8_t>> storage_get_binary(const std::string& key) const;
1605
-
1606
- /**
1607
- * Get a JSON document
1608
- * @param key Key to retrieve
1609
- * @return Optional containing value if found and type matches
1610
- */
1611
- std::optional<nlohmann::json> storage_get_json(const std::string& key) const;
1612
-
1613
- // Delete and Query Operations
1614
- /**
1615
- * Delete a key from storage
1616
- * @param key Key to delete
1617
- * @return true if key existed and was deleted
1618
- */
1619
- bool storage_delete(const std::string& key);
1620
-
1621
- /**
1622
- * Check if a key exists in storage
1623
- * @param key Key to check
1624
- * @return true if key exists
1625
- */
1626
- bool storage_has(const std::string& key) const;
1627
-
1628
- /**
1629
- * Get all keys in storage
1630
- * @return Vector of all keys
1631
- */
1632
- std::vector<std::string> storage_keys() const;
1633
-
1634
- /**
1635
- * Get keys matching a prefix
1636
- * @param prefix Prefix to match
1637
- * @return Vector of matching keys
1638
- */
1639
- std::vector<std::string> storage_keys_with_prefix(const std::string& prefix) const;
1640
-
1641
- /**
1642
- * Get the number of entries in storage
1643
- * @return Number of entries
1644
- */
1645
- size_t storage_size() const;
1646
-
1647
- // Synchronization
1648
- /**
1649
- * Request storage sync from connected peers
1650
- * @return true if sync request was sent
1651
- */
1652
- bool storage_request_sync();
1653
-
1654
- /**
1655
- * Check if storage is synchronized
1656
- * @return true if initial sync is complete
1657
- */
1658
- bool is_storage_synced() const;
1659
-
1660
- // Statistics
1661
- /**
1662
- * Get storage statistics
1663
- * @return JSON object with storage statistics
1664
- */
1665
- nlohmann::json get_storage_statistics() const;
1666
-
1667
- /**
1668
- * Set storage configuration
1669
- * @param config Storage configuration settings
1670
- */
1671
- void set_storage_config(const StorageConfig& config);
1672
-
1673
- /**
1674
- * Get current storage configuration
1675
- * @return Current configuration settings
1676
- */
1677
- const StorageConfig& get_storage_config() const;
1678
-
1679
- // Event Handlers
1680
- /**
1681
- * Set storage change callback
1682
- * @param callback Function to call when storage changes
1683
- */
1684
- void on_storage_change(StorageChangeCallback callback);
1685
-
1686
- /**
1687
- * Set storage sync complete callback
1688
- * @param callback Function to call when sync completes
1689
- */
1690
- void on_storage_sync_complete(StorageSyncCompleteCallback callback);
1691
- #endif // RATS_STORAGE
1692
-
1693
- #ifdef RATS_SEARCH_FEATURES
1694
- // =========================================================================
1695
- // BitTorrent API (requires RATS_SEARCH_FEATURES)
1696
- // =========================================================================
1697
-
1698
- /**
1699
- * Enable BitTorrent functionality
1700
- * @param listen_port Port to listen for BitTorrent connections (default: 6881)
1701
- * @return true if BitTorrent was successfully enabled
1702
- */
1703
- bool enable_bittorrent(int listen_port = 6881);
1704
-
1705
- /**
1706
- * Set the directory for storing resume data files
1707
- * Resume data allows torrents to resume from where they left off.
1708
- * Should be called after enable_bittorrent() and before adding torrents.
1709
- * @param path Directory path for resume data (e.g., app data folder)
1710
- */
1711
- void set_resume_data_path(const std::string& path);
1712
-
1713
- /**
1714
- * Disable BitTorrent functionality
1715
- */
1716
- void disable_bittorrent();
1717
-
1718
- /**
1719
- * Check if BitTorrent is enabled
1720
- * @return true if BitTorrent is active
1721
- */
1722
- bool is_bittorrent_enabled() const;
1723
-
1724
- /**
1725
- * Add a torrent from a file
1726
- * @param torrent_file Path to the .torrent file
1727
- * @param download_path Directory where files will be downloaded
1728
- * @return Shared pointer to TorrentDownload object, or nullptr on failure
1729
- */
1730
- std::shared_ptr<TorrentDownload> add_torrent(const std::string& torrent_file,
1731
- const std::string& download_path);
1732
-
1733
- /**
1734
- * Add a torrent from TorrentInfo
1735
- * @param torrent_info TorrentInfo object with torrent metadata
1736
- * @param download_path Directory where files will be downloaded
1737
- * @return Shared pointer to TorrentDownload object, or nullptr on failure
1738
- */
1739
- std::shared_ptr<TorrentDownload> add_torrent(const TorrentInfo& torrent_info,
1740
- const std::string& download_path);
1741
-
1742
- /**
1743
- * Add a torrent by info hash (magnet link style - uses DHT to find peers)
1744
- * @param info_hash Info hash of the torrent
1745
- * @param download_path Directory where files will be downloaded
1746
- * @return Shared pointer to TorrentDownload object, or nullptr on failure
1747
- * @note Requires DHT to be running. Will discover peers via DHT.
1748
- */
1749
- std::shared_ptr<TorrentDownload> add_torrent_by_hash(const InfoHash& info_hash,
1750
- const std::string& download_path);
1751
-
1752
- /**
1753
- * Add a torrent by info hash hex string (magnet link style - uses DHT to find peers)
1754
- * @param info_hash_hex Info hash as 40-character hex string
1755
- * @param download_path Directory where files will be downloaded
1756
- * @return Shared pointer to TorrentDownload object, or nullptr on failure
1757
- * @note Requires DHT to be running. Will discover peers via DHT.
1758
- */
1759
- std::shared_ptr<TorrentDownload> add_torrent_by_hash(const std::string& info_hash_hex,
1760
- const std::string& download_path);
1761
-
1762
- /**
1763
- * Remove a torrent by info hash
1764
- * @param info_hash Info hash of the torrent to remove
1765
- * @return true if torrent was removed successfully
1766
- */
1767
- bool remove_torrent(const InfoHash& info_hash);
1768
-
1769
- /**
1770
- * Get a torrent by info hash
1771
- * @param info_hash Info hash of the torrent
1772
- * @return Shared pointer to TorrentDownload object, or nullptr if not found
1773
- */
1774
- std::shared_ptr<TorrentDownload> get_torrent(const InfoHash& info_hash);
1775
-
1776
- /**
1777
- * Get all active torrents
1778
- * @return Vector of all active torrent downloads
1779
- */
1780
- std::vector<std::shared_ptr<TorrentDownload>> get_all_torrents();
1781
-
1782
- /**
1783
- * Get the number of active torrents
1784
- * @return Number of active torrents
1785
- */
1786
- size_t get_active_torrents_count() const;
1787
-
1788
- /**
1789
- * Get BitTorrent statistics (downloaded and uploaded bytes)
1790
- * @return Pair of (downloaded_bytes, uploaded_bytes)
1791
- */
1792
- std::pair<uint64_t, uint64_t> get_bittorrent_stats() const;
1793
-
1794
- /**
1795
- * Get torrent metadata without downloading (requires DHT to be running)
1796
- * @param info_hash Info hash of the torrent
1797
- * @param callback Function called when metadata is retrieved (torrent_info, success, error_message)
1798
- * @note This only retrieves metadata via BEP 9, it does not start downloading
1799
- */
1800
- void get_torrent_metadata(const InfoHash& info_hash,
1801
- std::function<void(const TorrentInfo&, bool, const std::string&)> callback);
1802
-
1803
- /**
1804
- * Get torrent metadata without downloading by hex string (requires DHT to be running)
1805
- * @param info_hash_hex Info hash as 40-character hex string
1806
- * @param callback Function called when metadata is retrieved (torrent_info, success, error_message)
1807
- * @note This only retrieves metadata via BEP 9, it does not start downloading
1808
- */
1809
- void get_torrent_metadata(const std::string& info_hash_hex,
1810
- std::function<void(const TorrentInfo&, bool, const std::string&)> callback);
1811
-
1812
- /**
1813
- * Get torrent metadata directly from a specific peer (fast path - no DHT search needed)
1814
- * This is more efficient when you already know a peer that has the torrent (e.g., from announce_peer)
1815
- * @param info_hash Info hash of the torrent
1816
- * @param peer_ip IP address of the peer
1817
- * @param peer_port Port of the peer
1818
- * @param callback Function called when metadata is retrieved (torrent_info, success, error_message)
1819
- * @note This only retrieves metadata via BEP 9, it does not start downloading
1820
- */
1821
- void get_torrent_metadata_from_peer(const InfoHash& info_hash,
1822
- const std::string& peer_ip,
1823
- uint16_t peer_port,
1824
- std::function<void(const TorrentInfo&, bool, const std::string&)> callback);
1825
-
1826
- /**
1827
- * Get torrent metadata directly from a specific peer by hex string (fast path)
1828
- * @param info_hash_hex Info hash as 40-character hex string
1829
- * @param peer_ip IP address of the peer
1830
- * @param peer_port Port of the peer
1831
- * @param callback Function called when metadata is retrieved (torrent_info, success, error_message)
1832
- * @note This only retrieves metadata via BEP 9, it does not start downloading
1833
- */
1834
- void get_torrent_metadata_from_peer(const std::string& info_hash_hex,
1835
- const std::string& peer_ip,
1836
- uint16_t peer_port,
1837
- std::function<void(const TorrentInfo&, bool, const std::string&)> callback);
1838
-
1839
- // =========================================================================
1840
- // Torrent Creation API (requires RATS_SEARCH_FEATURES)
1841
- // =========================================================================
1842
-
1843
- /**
1844
- * Torrent creation progress callback type
1845
- * Called during piece hashing to report progress
1846
- * @param current_piece Current piece being hashed (0-indexed)
1847
- * @param total_pieces Total number of pieces
1848
- */
1849
- using TorrentCreationProgressCallback = std::function<void(uint32_t current_piece, uint32_t total_pieces)>;
1850
-
1851
- /**
1852
- * Create a torrent from a file or directory and return TorrentInfo
1853
- * This is a synchronous operation that reads all files to compute piece hashes.
1854
- * @param path Path to file or directory to create torrent from
1855
- * @param trackers Optional list of tracker URLs
1856
- * @param comment Optional comment
1857
- * @param progress_callback Optional callback for progress updates
1858
- * @return TorrentInfo object, or nullopt on failure
1859
- */
1860
- std::optional<TorrentInfo> create_torrent_from_path(
1861
- const std::string& path,
1862
- const std::vector<std::string>& trackers = {},
1863
- const std::string& comment = "",
1864
- TorrentCreationProgressCallback progress_callback = nullptr);
1865
-
1866
- /**
1867
- * Create a torrent from a file or directory and return raw torrent data
1868
- * @param path Path to file or directory
1869
- * @param trackers Optional list of tracker URLs
1870
- * @param comment Optional comment
1871
- * @param progress_callback Optional callback for progress updates
1872
- * @return Bencoded torrent data, or empty vector on failure
1873
- */
1874
- std::vector<uint8_t> create_torrent_data(
1875
- const std::string& path,
1876
- const std::vector<std::string>& trackers = {},
1877
- const std::string& comment = "",
1878
- TorrentCreationProgressCallback progress_callback = nullptr);
1879
-
1880
- /**
1881
- * Create a torrent and save it to a file
1882
- * @param path Path to file or directory
1883
- * @param output_file Path to save the .torrent file
1884
- * @param trackers Optional list of tracker URLs
1885
- * @param comment Optional comment
1886
- * @param progress_callback Optional callback for progress updates
1887
- * @return true if torrent was created and saved successfully
1888
- */
1889
- bool create_torrent_file(
1890
- const std::string& path,
1891
- const std::string& output_file,
1892
- const std::vector<std::string>& trackers = {},
1893
- const std::string& comment = "",
1894
- TorrentCreationProgressCallback progress_callback = nullptr);
1895
-
1896
- /**
1897
- * Create a torrent, add it to the BitTorrent client, and start seeding
1898
- * This combines torrent creation with immediately starting to seed it.
1899
- * @param path Path to file or directory
1900
- * @param trackers Optional list of tracker URLs
1901
- * @param comment Optional comment
1902
- * @param progress_callback Optional callback for progress updates
1903
- * @return Shared pointer to TorrentDownload for the seeding torrent, or nullptr on failure
1904
- * @note Requires BitTorrent to be enabled (call enable_bittorrent() first)
1905
- */
1906
- std::shared_ptr<TorrentDownload> create_and_seed_torrent(
1907
- const std::string& path,
1908
- const std::vector<std::string>& trackers = {},
1909
- const std::string& comment = "",
1910
- TorrentCreationProgressCallback progress_callback = nullptr);
1911
-
1912
- // =========================================================================
1913
- // Spider Mode API (requires RATS_SEARCH_FEATURES)
1914
- // =========================================================================
1915
-
1916
- /**
1917
- * Spider announce callback type
1918
- * Called when a peer announces they have a torrent (announce_peer request received)
1919
- * @param info_hash The info hash being announced (as hex string)
1920
- * @param peer_address The peer that is announcing (ip:port format)
1921
- */
1922
- using SpiderAnnounceCallback = std::function<void(const std::string& info_hash, const std::string& peer_address)>;
1923
-
1924
- /**
1925
- * Enable spider mode on DHT
1926
- * In spider mode:
1927
- * - Nodes are added to routing table without ping verification
1928
- * - All announce_peer requests from other peers are collected via callback
1929
- * @param enable true to enable spider mode, false to disable
1930
- */
1931
- void set_spider_mode(bool enable);
1932
-
1933
- /**
1934
- * Check if spider mode is enabled
1935
- * @return true if spider mode is enabled
1936
- */
1937
- bool is_spider_mode() const;
1938
-
1939
- /**
1940
- * Set callback for announce_peer requests (spider mode)
1941
- * Called when other peers announce they have a torrent
1942
- * @param callback The callback to invoke
1943
- */
1944
- void set_spider_announce_callback(SpiderAnnounceCallback callback);
1945
-
1946
- /**
1947
- * Set spider ignore mode - when true, incoming requests are not processed
1948
- * Useful for rate limiting in spider mode
1949
- * @param ignore true to ignore incoming requests, false to process them
1950
- */
1951
- void set_spider_ignore(bool ignore);
1952
-
1953
- /**
1954
- * Check if spider ignore mode is enabled
1955
- * @return true if ignoring incoming requests
1956
- */
1957
- bool is_spider_ignoring() const;
1958
-
1959
- /**
1960
- * Trigger a single spider walk iteration
1961
- * Sends find_node to a random node from the spider pool
1962
- * Call this periodically at desired frequency to discover new nodes
1963
- */
1964
- void spider_walk();
1965
-
1966
- /**
1967
- * Get the size of the spider node pool
1968
- * @return Number of nodes in spider pool
1969
- */
1970
- size_t get_spider_pool_size() const;
1971
-
1972
- /**
1973
- * Get the number of visited nodes in spider mode
1974
- * @return Number of visited nodes
1975
- */
1976
- size_t get_spider_visited_count() const;
1977
-
1978
- /**
1979
- * Clear spider state (pool and visited nodes)
1980
- * Useful for resetting the spider walk
1981
- */
1982
- void clear_spider_state();
1983
- #endif // RATS_SEARCH_FEATURES
1984
-
1985
- private:
1986
- int listen_port_;
1987
- std::string bind_address_;
1988
- int max_peers_;
1989
- socket_t server_socket_;
1990
- std::atomic<bool> running_;
1991
-
1992
- // =========================================================================
1993
- // MUTEX LOCKING ORDER - CRITICAL FOR DEADLOCK PREVENTION
1994
- // =========================================================================
1995
- // When acquiring multiple mutexes, ALWAYS follow this strict order:
1996
- //
1997
- // 1. config_mutex_ (Configuration and peer ID)
1998
- // 2. protocol_config_mutex_ (Protocol name and version)
1999
- // 3. encryption_mutex_ (Encryption settings and keys)
2000
- // 4. local_addresses_mutex_ (Local interface addresses)
2001
- // 5. peers_mutex_ (Peer management - most frequently locked)
2002
- // 6. io_mutex_ (I/O poller and send buffer access)
2003
- // 7. message_handlers_mutex_ (Message handler registration)
2004
- // 8. reconnect_mutex_ (Reconnection queue management)
2005
- // 9. port_mapping_mutex_ (UPnP/NAT-PMP backends and mapped address)
2006
- // 10. network_monitor_mutex_ / network_recovery_mutex_ (network-change state)
2007
- //
2008
- // (9) and (10) are leaf locks: they are never held while acquiring any lock
2009
- // above, so they impose no additional ordering constraints.
2010
- // =========================================================================
2011
-
2012
- // [1] Configuration persistence (protected by config_mutex_)
2013
- mutable std::mutex config_mutex_; // [1] Protects configuration data
2014
- std::string our_peer_id_; // Our persistent peer ID
2015
- std::string data_directory_; // Directory where data files are stored
2016
- static const std::string CONFIG_FILE_NAME; // "config.json"
2017
- static const std::string PEERS_FILE_NAME; // "peers.rats"
2018
- static const std::string PEERS_EVER_FILE_NAME; // "peers_ever.rats"
2019
-
2020
- // [2] Custom protocol configuration (protected by protocol_config_mutex_)
2021
- mutable std::mutex protocol_config_mutex_; // [2] Protects protocol configuration
2022
- std::string custom_protocol_name_; // Custom protocol name (default: "rats")
2023
- std::string custom_protocol_version_; // Custom protocol version (default: "1.0")
2024
-
2025
- // [3] Encryption state (protected by encryption_mutex_)
2026
- mutable std::mutex encryption_mutex_; // [3] Protects encryption state
2027
- bool encryption_enabled_; // Whether encryption is enabled
2028
- rats::NoiseKeyPair noise_static_keypair_; // Our static Noise keypair
2029
- bool noise_keypair_initialized_; // Whether keypair has been initialized
2030
-
2031
- // [4] Local interface address blocking (protected by local_addresses_mutex_)
2032
- mutable std::mutex local_addresses_mutex_; // [4] Protects local interface addresses
2033
- std::unordered_set<std::string> local_interface_addresses_;
2034
- // Subset of local_interface_addresses_ that came from interface enumeration.
2035
- // Tracked separately so a network-change refresh can drop only stale auto
2036
- // entries without evicting localhost or externally-discovered addresses
2037
- // (STUN reflexive, mapped external IP, user add_ignored_address()).
2038
- std::unordered_set<std::string> auto_interface_addresses_;
2039
-
2040
- // [5] Organized peer management using RatsPeer struct (protected by peers_mutex_)
2041
- mutable std::mutex peers_mutex_; // [5] Protects peer data (most frequently locked)
2042
- std::unordered_map<std::string, RatsPeer> peers_; // keyed by peer_id
2043
- std::unordered_map<socket_t, std::string> socket_to_peer_id_; // for quick socket->peer_id lookup
2044
- std::unordered_map<std::string, std::string> address_to_peer_id_; // for duplicate detection (normalized_address->peer_id)
2045
- std::atomic<int> validated_peer_count_{0}; // Cached count of peers with COMPLETED handshake
2046
-
2047
- // [6] Async I/O (poller + io thread)
2048
- std::unique_ptr<IOPoller> poller_;
2049
- std::mutex io_mutex_; // Protects poller_ and send-buffer writes from non-IO threads
2050
- std::thread io_thread_;
2051
- std::thread management_thread_;
2052
-
2053
- ConnectionCallback connection_callback_;
2054
- BinaryDataCallback binary_data_callback_;
2055
- StringDataCallback string_data_callback_;
2056
- JsonDataCallback json_data_callback_;
2057
- DisconnectCallback disconnect_callback_;
2058
-
2059
- // DHT clients for peer discovery. IPv4 and IPv6 are separate Kademlia networks
2060
- // (BEP 32), so each family runs its own client. dht_client_ (IPv4) is also the one
2061
- // shared with the BitTorrent subsystem; dht_client_v6_ is created best-effort when
2062
- // IPv6 is available.
2063
- std::unique_ptr<DhtClient> dht_client_;
2064
- std::unique_ptr<DhtClient> dht_client_v6_;
2065
-
2066
- // mDNS client for local network discovery
2067
- std::unique_ptr<MdnsClient> mdns_client_;
2068
- std::function<void(const std::string&, int, const std::string&)> mdns_callback_;
2069
-
2070
- // GossipSub for publish-subscribe messaging
2071
- std::unique_ptr<GossipSub> gossipsub_;
2072
-
2073
- // File transfer manager
2074
- std::unique_ptr<FileTransferManager> file_transfer_manager_;
2075
-
2076
- // ICE manager for NAT traversal
2077
- std::unique_ptr<IceManager> ice_manager_;
2078
-
2079
- // Automatic port forwarding (UPnP IGD + NAT-PMP). Implemented in librats_portmap.cpp.
2080
- mutable std::mutex port_mapping_mutex_; // guards the fields below
2081
- PortMappingConfig port_mapping_config_;
2082
- std::unique_ptr<UpnpClient> upnp_client_;
2083
- std::unique_ptr<NatPmpClient> natpmp_client_;
2084
- PortMapCallback port_mapping_callback_;
2085
- // Public address discovered by the backends. The external port is tracked per
2086
- // protocol (like libtorrent's per-listen-socket tcp/udp port mappings): the TCP
2087
- // mapping forwards the peer listen port, the UDP mapping forwards the DHT port.
2088
- // A single field would let the two backend callbacks clobber each other.
2089
- std::string mapped_external_ip_;
2090
- uint16_t mapped_external_tcp_port_ = 0; // public port for the TCP peer-listen port
2091
- uint16_t mapped_external_udp_port_ = 0; // public port for the UDP DHT port
2092
- // Set once we warn that the gateway's reported external IP is itself private
2093
- // (double-NAT), so the warning isn't repeated on every lease refresh.
2094
- bool double_nat_warning_logged_ = false;
2095
-
2096
- // Start/stop the port mapping backends (no-ops if disabled). Called from
2097
- // start()/stop(); safe to call repeatedly.
2098
- void start_port_mapping();
2099
- void stop_port_mapping();
2100
- void handle_port_mapping_result(const PortMapResult& result);
2101
- // Public TCP port to advertise to peers/DHT: the mapped external port once a
2102
- // TCP mapping is established, otherwise the local listen port.
2103
- uint16_t get_advertised_port() const;
2104
-
2105
- // Network change detection (implemented in librats_portmap.cpp). Monitor runs
2106
- // a platform watcher; on a real address-set change it refreshes the self-
2107
- // address set inline and wakes the recovery worker, which re-maps ports,
2108
- // re-discovers the public IP and re-announces. These mutexes are last in the
2109
- // lock order (after [8]) and are never held while calling into other
2110
- // subsystems, so they introduce no new ordering constraints.
2111
- std::unique_ptr<NetworkMonitor> network_monitor_;
2112
- bool network_change_detection_enabled_ = true; // start the monitor on start()
2113
- mutable std::mutex network_monitor_mutex_; // guards the user callback below
2114
- NetworkChangeCallback network_change_callback_;
2115
- // Dedicated recovery worker: serialises the slow recovery work (STUN can
2116
- // block for seconds) off the monitor thread and coalesces rapid changes.
2117
- std::thread network_recovery_thread_;
2118
- std::mutex network_recovery_mutex_;
2119
- std::condition_variable network_recovery_cv_;
2120
- bool network_recovery_pending_ = false;
2121
- bool network_recovery_stop_ = false;
2122
-
2123
- void start_network_monitor();
2124
- void stop_network_monitor();
2125
- void network_recovery_loop();
2126
- void handle_network_change(const std::vector<std::string>& current_addresses);
2127
- void recover_after_network_change();
2128
-
2129
- #ifdef RATS_STORAGE
2130
- // Distributed storage manager (optional, requires RATS_STORAGE)
2131
- std::unique_ptr<StorageManager> storage_manager_;
2132
- #endif
2133
-
2134
- #ifdef RATS_SEARCH_FEATURES
2135
- // BitTorrent client (optional, requires RATS_SEARCH_FEATURES)
2136
- std::unique_ptr<BitTorrentClient> bittorrent_client_;
2137
- #endif
2138
-
2139
- void initialize_modules();
2140
- void destroy_modules();
2141
-
2142
- // Async I/O loop (single thread for all sockets)
2143
- void io_loop();
2144
- void management_loop();
2145
-
2146
- // I/O event handlers (called from io_loop)
2147
- void accept_incoming();
2148
- bool handle_readable(socket_t socket);
2149
- bool handle_writable(socket_t socket);
2150
- void handle_disconnect(socket_t socket);
2151
-
2152
- // Poller registration helpers
2153
- void poller_add(socket_t fd, uint32_t events);
2154
- void poller_modify(socket_t fd, uint32_t events);
2155
- void poller_remove(socket_t fd);
2156
-
2157
- // Helpers – post-handshake and message routing
2158
- void handle_post_handshake_completion(socket_t socket, const RatsPeer& peer_copy);
2159
- void process_message(socket_t socket, const std::vector<uint8_t>& data, const std::string& peer_id);
2160
-
2161
- // Peer lookup helper (assumes peers_mutex_ is already locked)
2162
- std::unordered_map<std::string, RatsPeer>::iterator find_peer_by_socket_unlocked(socket_t socket);
2163
- std::unordered_map<std::string, RatsPeer>::const_iterator find_peer_by_socket_unlocked(socket_t socket) const;
2164
-
2165
- void remove_peer(socket_t socket);
2166
- std::string generate_temporary_peer_id(socket_t socket, const std::string& connection_info);
2167
- void handle_dht_peer_discovery(const std::vector<Peer>& peers, const InfoHash& info_hash);
2168
- void handle_mdns_service_discovery(const MdnsService& service, bool is_new);
2169
-
2170
- // Message header helpers
2171
- std::vector<uint8_t> create_message_with_header(const std::vector<uint8_t>& payload, MessageDataType type);
2172
- bool parse_message_with_header(const std::vector<uint8_t>& message, MessageHeader& header, std::vector<uint8_t>& payload) const;
2173
-
2174
- // Peer management methods using RatsPeer
2175
- void add_peer_unlocked(const RatsPeer& peer); // Assumes peers_mutex_ is already locked
2176
- void remove_peer_by_id_unlocked(const std::string& peer_id); // Assumes peers_mutex_ is already locked
2177
- void mark_manual_disconnect(const std::string& peer_id);
2178
- static std::vector<uint8_t> json_to_binary(const nlohmann::json& data);
2179
- bool is_already_connected_to_address(const std::string& normalized_address) const;
2180
- std::string normalize_peer_address(const std::string& ip, int port) const;
2181
-
2182
- // Async send – enqueues a framed (length-prefixed) message into the peer's
2183
- // ChainedSendBuffer and arms PollOut. Thread-safe (acquires io_mutex_).
2184
- // Returns false if the peer was not found.
2185
- bool enqueue_message(socket_t socket, const std::vector<uint8_t>& data);
2186
- // Unlocked variant – caller must hold peers_mutex_
2187
- bool enqueue_message_unlocked(RatsPeer& peer, const std::vector<uint8_t>& data);
2188
-
2189
- // Lightweight snapshot of peer data needed for sending (avoids holding peers_mutex_ during enqueue)
2190
- struct PeerSendTarget {
2191
- socket_t socket;
2192
- std::string peer_id;
2193
- std::shared_ptr<rats::NoiseCipherState> send_cipher;
2194
- };
2195
-
2196
- bool send_binary_to_peer_unlocked(socket_t socket, const std::vector<uint8_t>& data,
2197
- MessageDataType message_type,
2198
- std::shared_ptr<rats::NoiseCipherState> send_cipher,
2199
- const std::string& peer_id_for_logging);
2200
-
2201
- // Async Noise handshake – processes one Noise XX message received from peer.
2202
- // Returns false if peer should be disconnected. Called from handle_readable.
2203
- bool handle_noise_frame(RatsPeer& peer);
2204
- // Kick-off: initialises noise_hs and writes first outgoing message if initiator.
2205
- void start_noise_handshake_async(RatsPeer& peer);
2206
-
2207
- // Local interface address blocking helper functions
2208
- void initialize_local_addresses();
2209
- bool is_blocked_address(const std::string& ip_address) const;
2210
- bool should_ignore_peer(const std::string& ip, int port) const;
2211
- bool can_connect_to_peer(const std::string& ip, int port) const;
2212
- static bool parse_address_string(const std::string& address_str, std::string& out_ip, int& out_port);
2213
-
2214
- // Helper functions that assume mutex is already locked
2215
- int get_peer_count_unlocked() const; // Helper that assumes peers_mutex_ is already locked
2216
-
2217
- // Protocol constants
2218
- static constexpr const char* RATS_PROTOCOL_VERSION = "1.0";
2219
- static constexpr int HANDSHAKE_TIMEOUT_SECONDS = 10;
2220
- static constexpr int TCP_CONNECT_TIMEOUT_MS = 10000; // 10 second TCP connection timeout
2221
- static constexpr int IO_POLL_TIMEOUT_MS = 100; // IO poller tick interval (ms)
2222
- static constexpr size_t MAX_FRAME_SIZE = 100 * 1024 * 1024; // 100 MB max single frame
2223
- static constexpr int PEER_RECONNECT_DELAY_MS = 100; // Delay before reconnecting saved peers
2224
- static constexpr int HISTORICAL_RECONNECT_DELAY_MS = 500; // Delay before reconnecting historical peers
2225
- static constexpr int MANAGEMENT_LOOP_INTERVAL_SECONDS = 2; // Management loop tick interval
2226
- static constexpr int THREAD_CLEANUP_INTERVAL_SECONDS = 30; // Thread cleanup interval
2227
- static constexpr int INITIAL_DISCOVERY_DELAY_SECONDS = 5; // DHT bootstrap delay
2228
- static constexpr int MAX_PEERS_REQUEST_COUNT = 5; // Max peers to request/respond
2229
- static constexpr int CONTENT_HASH_HEX_LENGTH = 40; // 160-bit hash as hex
2230
- static constexpr int64_t TIMESTAMP_SKEW_TOLERANCE_MS = 10LL * 60LL * 1000LL; // 10 minutes
2231
-
2232
- struct HandshakeMessage {
2233
- std::string protocol;
2234
- std::string version;
2235
- std::string peer_id;
2236
- std::string message_type;
2237
- int64_t timestamp;
2238
- bool encryption_enabled; // Whether peer supports/wants encryption
2239
- uint16_t listen_port; // Peer's listening port for peer exchange
2240
- };
2241
-
2242
- std::string create_handshake_message(const std::string& message_type, const std::string& our_peer_id) const;
2243
- bool parse_handshake_message(const std::vector<uint8_t>& data, HandshakeMessage& out_msg) const;
2244
- bool validate_handshake_message(const HandshakeMessage& msg) const;
2245
- bool is_handshake_message(const std::vector<uint8_t>& data) const;
2246
- bool send_handshake_unlocked(RatsPeer& peer, const std::string& our_peer_id); // enqueues via send buffer (peers_mutex_ held)
2247
- bool handle_handshake_message(socket_t socket, const std::string& initial_peer_id, const std::vector<uint8_t>& data);
2248
- void check_handshake_timeouts();
2249
- void log_handshake_completion_unlocked(const RatsPeer& peer);
2250
-
2251
- // Automatic discovery
2252
- std::atomic<bool> auto_discovery_running_;
2253
- std::thread auto_discovery_thread_;
2254
- void automatic_discovery_loop();
2255
- void announce_rats_peer();
2256
-
2257
- // Message handling system
2258
- nlohmann::json create_rats_message(const std::string& type, const nlohmann::json& payload, const std::string& sender_peer_id);
2259
- void handle_rats_message(socket_t socket, const std::string& peer_id, const nlohmann::json& message);
2260
-
2261
- // Specific message handlers
2262
- void handle_peer_exchange_message(socket_t socket, const std::string& peer_id, const nlohmann::json& payload);
2263
- void handle_peers_request_message(socket_t socket, const std::string& peer_id, const nlohmann::json& payload);
2264
- void handle_peers_response_message(socket_t socket, const std::string& peer_id, const nlohmann::json& payload);
2265
-
2266
- // Message creation and broadcasting
2267
- nlohmann::json create_peer_exchange_message(const RatsPeer& peer);
2268
- void broadcast_peer_exchange_message(const RatsPeer& new_peer);
2269
- nlohmann::json create_peers_request_message(const std::string& sender_peer_id);
2270
- nlohmann::json create_peers_response_message(const std::vector<RatsPeer>& peers, const std::string& sender_peer_id);
2271
- std::vector<RatsPeer> get_random_peers(int max_count, const std::string& exclude_peer_id = "") const;
2272
- void send_peers_request(socket_t socket, const std::string& our_peer_id);
2273
-
2274
- int broadcast_rats_message(const nlohmann::json& message, const std::string& exclude_peer_id = "", bool validated_only = true);
2275
-
2276
- // [7] Message exchange API implementation (protected by message_handlers_mutex_)
2277
- mutable std::mutex message_handlers_mutex_; // [7] Protects message handlers
2278
- struct MessageHandler {
2279
- MessageCallback callback;
2280
- bool is_once;
2281
-
2282
- MessageHandler(MessageCallback cb, bool once) : callback(cb), is_once(once) {}
2283
- };
2284
- std::unordered_map<std::string, std::vector<MessageHandler>> message_handlers_;
2285
-
2286
- void call_message_handlers(const std::string& message_type, const std::string& peer_id, const nlohmann::json& data);
2287
-
2288
- // [8] Automatic reconnection system (protected by reconnect_mutex_)
2289
- mutable std::mutex reconnect_mutex_; // [8] Protects reconnection queue
2290
- std::unordered_map<std::string, ReconnectInfo> reconnect_queue_; // keyed by peer_id
2291
- ReconnectConfig reconnect_config_; // Reconnection configuration
2292
- std::unordered_set<std::string> manual_disconnect_peers_; // Peers that were manually disconnected (don't reconnect)
2293
-
2294
- // Reconnection helper methods
2295
- void schedule_reconnect(const RatsPeer& peer);
2296
- void process_reconnect_queue();
2297
- void remove_from_reconnect_queue(const std::string& peer_id);
2298
- int get_retry_interval_seconds(int attempt, bool is_stable) const;
2299
-
2300
- // Configuration persistence helpers
2301
- std::string generate_persistent_peer_id() const;
2302
- nlohmann::json serialize_peer_for_persistence(const RatsPeer& peer) const;
2303
- bool deserialize_peer_from_persistence(const nlohmann::json& json, std::string& ip, int& port, std::string& peer_id) const;
2304
- std::string get_config_file_path() const;
2305
- std::string get_peers_file_path() const;
2306
- std::string get_peers_ever_file_path() const;
2307
- bool save_peers_to_file();
2308
- bool append_peer_to_historical_file(const RatsPeer& peer);
2309
- int load_and_reconnect_historical_peers();
2310
-
2311
- // Noise Protocol encryption helpers
2312
- void initialize_noise_keypair();
2313
- };
2314
-
2315
- // Utility functions
2316
- std::unique_ptr<RatsClient> create_rats_client(int listen_port);
2317
-
2318
- // Library version query (stable, binding-friendly)
2319
- RATS_API const char* rats_get_library_version_string();
2320
- RATS_API void rats_get_library_version(int* major, int* minor, int* patch, int* build);
2321
- RATS_API const char* rats_get_library_git_describe();
2322
- RATS_API uint32_t rats_get_library_abi(); // packed as (major<<16)|(minor<<8)|patch
2323
-
2324
- } // namespace librats