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
@@ -0,0 +1,148 @@
1
+ #pragma once
2
+
3
+ /**
4
+ * @file peer_table.h
5
+ * @brief Control-plane registry: PeerId → route + metadata.
6
+ *
7
+ * This is the only shared peer structure in the redesign, and it is deliberately
8
+ * **off the per-byte data path**: it is touched on connect/disconnect and on
9
+ * explicit by-id lookups (send-by-id, peers()), never per inbound/outbound frame
10
+ * (those use the route carried in the Connection/Peer handle). It is therefore
11
+ * read-mostly and guarded by a shared_mutex with short critical sections — a
12
+ * world away from the old global peers_mutex_ held across recv/send.
13
+ */
14
+
15
+ #include "librats/util/rats_export.h"
16
+ #include "librats/core/types.h" // ConnId
17
+ #include "librats/peer/peer_id.h"
18
+ #include "librats/peer/peer_info.h"
19
+
20
+ #include <atomic>
21
+ #include <cstdint>
22
+ #include <memory>
23
+ #include <optional>
24
+ #include <shared_mutex>
25
+ #include <unordered_map>
26
+ #include <vector>
27
+
28
+ namespace librats {
29
+
30
+ /// Where a peer's live connection lives: which reactor owns it, and its ConnId.
31
+ /// (reactor, conn) identifies a connection globally and is never reused while it
32
+ /// is alive, so it is the stable key for matching a teardown to a directory entry.
33
+ struct PeerRoute {
34
+ uint8_t reactor = 0;
35
+ ConnId conn = kInvalidConnId;
36
+
37
+ bool operator==(const PeerRoute& o) const noexcept { return reactor == o.reactor && conn == o.conn; }
38
+ bool operator!=(const PeerRoute& o) const noexcept { return !(*this == o); }
39
+ };
40
+
41
+ class RATS_API PeerTable {
42
+ public:
43
+ enum class AddResult {
44
+ NewPeer, ///< First connection to this peer — caller should fire "connected".
45
+ Updated, ///< Same connection re-registered; metadata refreshed only.
46
+ Replaced, ///< A previous connection was superseded (`close` holds its route).
47
+ Rejected, ///< An existing connection was kept; the new one (`close`) must close.
48
+ };
49
+ struct AddOutcome {
50
+ AddResult result = AddResult::NewPeer;
51
+ std::optional<PeerRoute> close; ///< Loser of a duplicate race; tear it down.
52
+ };
53
+
54
+ /// Register a connection for a peer, resolving duplicates deterministically.
55
+ /// Both ends resolve the same pair of connections independently, so each rule
56
+ /// reads only what looks identical from either side — never arrival order:
57
+ /// - opposite roles ⇒ a simultaneous cross-connect. `prefer_outbound` (which
58
+ /// BOTH peers compute identically from a symmetric rule over their ids)
59
+ /// picks the surviving link, so both converge on the same one.
60
+ /// - same role, different transports ⇒ a dial race whose attempts both got
61
+ /// through; the datagram link wins at both ends.
62
+ /// - same role and transport ⇒ a reconnect, so the newcomer wins.
63
+ /// Taken together these are a total order, mirrored at the two ends, which is
64
+ /// what makes the verdict independent of the order connections arrive in. See
65
+ /// peer_table.cpp for why each rule is the one it is.
66
+ /// The loser's route is returned in `close`. Write lock.
67
+ AddOutcome add(const PeerInfo& info, PeerRoute route, bool prefer_outbound);
68
+
69
+ /// Drop a peer, but only if its current route matches `route` — so a stale
70
+ /// connection's teardown cannot evict a newer one that replaced it. Write lock.
71
+ /// Returns true iff an entry was actually removed.
72
+ bool remove(const PeerId& id, PeerRoute route);
73
+
74
+ /// Route to a peer's live connection, if connected. Read lock.
75
+ std::optional<PeerRoute> route(const PeerId& id) const;
76
+
77
+ /// Merge dialable addresses into a peer's metadata, de-duplicated and bounded
78
+ /// to kMaxAddressesPerPeer. Applies only if `route` is still the peer's live
79
+ /// route (a stale connection's late identify cannot mutate a newer link).
80
+ /// Returns the addresses actually added (i.e. not already known). Write lock.
81
+ std::vector<Address> add_addresses(const PeerId& id, PeerRoute route,
82
+ const std::vector<Address>& addresses);
83
+
84
+ /// Record which transports a peer advertised in its identify message. Applies
85
+ /// only while `route` is still the peer's live route. Write lock.
86
+ void set_supported_transports(const PeerId& id, PeerRoute route, uint8_t mask);
87
+
88
+ /// A peer's live route together with whether its send queue has room, in one
89
+ /// lookup — the send path needs both and should not pay for two.
90
+ struct Destination {
91
+ PeerRoute route;
92
+ bool writable = true;
93
+ /// The peer's in-transit counter (see Entry::owed). Shared, not copied,
94
+ /// so the caller charges the same counter the reactor task discharges.
95
+ std::shared_ptr<std::atomic<size_t>> owed;
96
+ };
97
+ std::optional<Destination> destination(const PeerId& id) const;
98
+
99
+ /// Whether every connected peer's send queue has room — what broadcast()
100
+ /// answers, since "may I send more?" to a fan-out is only usefully answered
101
+ /// by its slowest recipient.
102
+ bool all_writable() const;
103
+
104
+ /// Record that a peer's send queue filled up or drained. Applies only while
105
+ /// `route` is still the peer's live route. Write lock, but only ever taken
106
+ /// when the mark is actually crossed, which is rare.
107
+ void set_writable(const PeerId& id, PeerRoute route, bool writable);
108
+
109
+ /// Upper bound on stored addresses per peer — caps memory and stops a peer
110
+ /// from flooding us with bogus addresses via the identify/PEX path.
111
+ static constexpr size_t kMaxAddressesPerPeer = 32;
112
+
113
+ /// Metadata snapshot for a peer. Read lock.
114
+ std::optional<PeerInfo> info(const PeerId& id) const;
115
+
116
+ bool contains(const PeerId& id) const;
117
+
118
+ /// Snapshot of all known peers (for the public API / persistence). Read lock.
119
+ std::vector<PeerInfo> snapshot() const;
120
+
121
+ size_t size() const noexcept { return count_.load(std::memory_order_relaxed); }
122
+
123
+ private:
124
+ struct Entry {
125
+ PeerInfo info;
126
+ PeerRoute route;
127
+ /// Whether this peer's send queue has room. Maintained by the reactor as
128
+ /// the queue crosses its low-water mark, read by send() so a caller on
129
+ /// any thread gets an answer without having to reach into a connection it
130
+ /// does not own. Advisory by nature — it is a snapshot of a queue that is
131
+ /// draining as it is read, which is exactly what a backpressure hint is.
132
+ bool writable = true;
133
+ /// Bytes handed to the owning reactor by send() that it has not taken up
134
+ /// yet. The queue itself lives on the reactor thread and `writable` above
135
+ /// only ever reports what the reactor has already seen — so a caller in a
136
+ /// tight loop could hand over megabytes before a single one of them was
137
+ /// counted. This is that backlog, incremented by the caller and decremented
138
+ /// by the reactor task, so the answer covers both halves.
139
+ std::shared_ptr<std::atomic<size_t>> owed =
140
+ std::make_shared<std::atomic<size_t>>(0);
141
+ };
142
+
143
+ mutable std::shared_mutex mutex_;
144
+ std::unordered_map<PeerId, Entry, PeerId::Hash> peers_;
145
+ std::atomic<size_t> count_{0};
146
+ };
147
+
148
+ } // namespace librats
@@ -0,0 +1,66 @@
1
+ #pragma once
2
+
3
+ /**
4
+ * @file handshaker.h
5
+ * @brief Secure-channel handshake driver and the provider that creates one.
6
+ *
7
+ * A Handshaker is fed handshake messages until it yields a Session and the
8
+ * remote PeerId (or fails). It is transport-agnostic: the Connection frames its
9
+ * `out` bytes as Handshake frames and feeds inbound Handshake payloads back in.
10
+ *
11
+ * A SecurityProvider configures the whole node (one keypair / policy) and mints
12
+ * a fresh Handshaker per connection. Swapping NoiseSecurity ⇄ PlaintextSecurity
13
+ * changes the entire security posture without touching the transport.
14
+ */
15
+
16
+ #include "librats/util/rats_export.h"
17
+ #include "librats/core/bytes.h"
18
+ #include "librats/core/types.h" // ConnRole
19
+ #include "librats/peer/peer_id.h"
20
+ #include "librats/security/session.h"
21
+
22
+ #include <memory>
23
+ #include <string>
24
+
25
+ namespace librats {
26
+
27
+ /// Canonical bytes identifying an application protocol. Bound into the handshake
28
+ /// — as the Noise prologue, or exchanged-and-checked in the plaintext handshake —
29
+ /// so peers whose protocol differs cannot connect. The protocol string is an
30
+ /// opaque identity compared for exact equality; by convention it is "<name>/
31
+ /// <version>" (e.g. "librats/1.0"), but any difference at all is a distinct
32
+ /// protocol. A fixed context tag namespaces it away from other prologue uses.
33
+ inline std::string protocol_id(const std::string& protocol) {
34
+ return std::string("librats-proto\x1f", 14) + protocol; // tag + opaque id
35
+ }
36
+
37
+ class RATS_API Handshaker {
38
+ public:
39
+ struct Outcome {
40
+ enum Status { NeedMore, Done, Failed } status = NeedMore;
41
+ std::unique_ptr<Session> session; ///< valid iff status == Done
42
+ PeerId remote_id; ///< valid iff status == Done
43
+ };
44
+
45
+ virtual ~Handshaker() = default;
46
+
47
+ /// Called once when the transport is up. Appends the initial message, if
48
+ /// any (e.g. the initiator's first Noise message), to `out`. False on error.
49
+ virtual bool start(Bytes& out) = 0;
50
+
51
+ /// Consume one received handshake message; append any reply to `out`.
52
+ virtual Outcome consume(ByteView incoming, Bytes& out) = 0;
53
+ };
54
+
55
+ class RATS_API SecurityProvider {
56
+ public:
57
+ virtual ~SecurityProvider() = default;
58
+
59
+ /// Create a handshaker for a new connection in the given role.
60
+ virtual std::unique_ptr<Handshaker> create(ConnRole role) = 0;
61
+
62
+ /// This node's own identity.
63
+ virtual const PeerId& local_id() const = 0;
64
+ };
65
+
66
+ } // namespace librats
@@ -0,0 +1,43 @@
1
+ #pragma once
2
+
3
+ /**
4
+ * @file identity.h
5
+ * @brief A node's cryptographic identity: a static keypair and its derived PeerId.
6
+ *
7
+ * The PeerId is SHA-256 of the static public key, so identity travels with the
8
+ * key. Generate a fresh identity for an ephemeral node, or rebuild one from a
9
+ * persisted private key to keep a stable PeerId across restarts.
10
+ */
11
+
12
+ #include "librats/util/rats_export.h"
13
+ #include "librats/peer/peer_id.h"
14
+ #include "librats/crypto/noise.h"
15
+
16
+ #include <cstring>
17
+
18
+ namespace librats {
19
+
20
+ struct RATS_API Identity {
21
+ librats::NoiseKeyPair static_keypair;
22
+ PeerId id;
23
+
24
+ /// Create a brand-new random identity.
25
+ static Identity generate() {
26
+ Identity ident;
27
+ librats::noise_generate_keypair(ident.static_keypair);
28
+ ident.id = PeerId::from_public_key(ident.static_keypair.public_key, librats::NOISE_DH_SIZE);
29
+ return ident;
30
+ }
31
+
32
+ /// Rebuild a stable identity from a persisted 32-byte private key.
33
+ static Identity from_private_key(const uint8_t private_key[librats::NOISE_DH_SIZE]) {
34
+ Identity ident;
35
+ std::memcpy(ident.static_keypair.private_key, private_key, librats::NOISE_DH_SIZE);
36
+ librats::noise_derive_public_key(private_key, ident.static_keypair.public_key);
37
+ ident.static_keypair.has_keys = true;
38
+ ident.id = PeerId::from_public_key(ident.static_keypair.public_key, librats::NOISE_DH_SIZE);
39
+ return ident;
40
+ }
41
+ };
42
+
43
+ } // namespace librats
@@ -0,0 +1,122 @@
1
+ #include "librats/security/noise_security.h"
2
+ #include "librats/crypto/noise.h"
3
+ #include "librats/util/logger.h"
4
+
5
+ namespace librats {
6
+ namespace {
7
+
8
+ // Human-readable Noise failure reason for handshake diagnostics. Kept local: the
9
+ // crypto layer deliberately exposes only the enum, and this is its sole logger.
10
+ const char* noise_error_name(librats::NoiseError e) {
11
+ switch (e) {
12
+ case librats::NoiseError::OK: return "ok";
13
+ case librats::NoiseError::INVALID_STATE: return "invalid-state";
14
+ case librats::NoiseError::DECRYPT_FAILED: return "decrypt-failed";
15
+ case librats::NoiseError::MESSAGE_TOO_LARGE: return "message-too-large";
16
+ case librats::NoiseError::HANDSHAKE_NOT_COMPLETE: return "handshake-not-complete";
17
+ case librats::NoiseError::HANDSHAKE_ALREADY_COMPLETE: return "handshake-already-complete";
18
+ case librats::NoiseError::INVALID_KEY: return "invalid-key";
19
+ case librats::NoiseError::INTERNAL_ERROR: return "internal-error";
20
+ }
21
+ return "unknown";
22
+ }
23
+
24
+ /// Session backed by a completed librats::NoiseSession (owns its transport ciphers).
25
+ class NoiseSessionAdapter final : public Session {
26
+ public:
27
+ NoiseSessionAdapter(std::unique_ptr<librats::NoiseSession> session, PeerId remote)
28
+ : session_(std::move(session)), remote_id_(remote) {}
29
+
30
+ bool encrypt(ByteView plain, Bytes& out) override {
31
+ out.resize(plain.size() + librats::NOISE_TAG_SIZE);
32
+ const size_t n = session_->encrypt(plain.data(), plain.size(), out.data());
33
+ if (n == 0 && plain.size() != 0) return false;
34
+ out.resize(n);
35
+ return true;
36
+ }
37
+
38
+ bool decrypt(ByteView cipher, Bytes& out) override {
39
+ if (cipher.size() < librats::NOISE_TAG_SIZE) return false;
40
+ out.resize(cipher.size()); // plaintext is always shorter than ciphertext
41
+ const size_t n = session_->decrypt(cipher.data(), cipher.size(), out.data());
42
+ if (n == librats::NOISE_DECRYPT_FAILED) return false; // 0 is a valid (empty) frame
43
+ out.resize(n);
44
+ return true;
45
+ }
46
+
47
+ const PeerId& remote_id() const override { return remote_id_; }
48
+ bool is_secure() const override { return true; }
49
+
50
+ private:
51
+ std::unique_ptr<librats::NoiseSession> session_;
52
+ PeerId remote_id_;
53
+ };
54
+
55
+ /// Drives the Noise XX message exchange via librats::NoiseSession::handshake_step.
56
+ class NoiseHandshaker final : public Handshaker {
57
+ public:
58
+ NoiseHandshaker(const Identity& identity, bool initiator, ByteView prologue)
59
+ : session_(std::make_unique<librats::NoiseSession>()), initiator_(initiator) {
60
+ session_->start(initiator, &identity.static_keypair,
61
+ prologue.empty() ? nullptr : prologue.data(), prologue.size());
62
+ }
63
+
64
+ bool start(Bytes& out) override {
65
+ if (!initiator_) return true; // responder waits for the first message
66
+ return step(nullptr, 0, out);
67
+ }
68
+
69
+ Outcome consume(ByteView incoming, Bytes& out) override {
70
+ Outcome oc;
71
+ if (!step(incoming.data(), incoming.size(), out)) {
72
+ oc.status = Outcome::Failed;
73
+ return oc;
74
+ }
75
+ if (session_->is_handshake_complete()) {
76
+ oc.remote_id = PeerId::from_public_key(session_->get_remote_static_public(),
77
+ librats::NOISE_DH_SIZE);
78
+ oc.session = std::make_unique<NoiseSessionAdapter>(std::move(session_), oc.remote_id);
79
+ oc.status = Outcome::Done;
80
+ }
81
+ return oc;
82
+ }
83
+
84
+ private:
85
+ // Run one handshake step; append the outgoing message (if any) to `out`.
86
+ bool step(const uint8_t* received, size_t received_len, Bytes& out) {
87
+ // A Noise transport message is capped at 65535 bytes; reject anything
88
+ // larger before it reaches the state machine. Defense in depth: the
89
+ // block layer admits frames up to kMaxBlockSize (64 MB), so without
90
+ // this an oversized handshake frame would be fed straight in.
91
+ if (received_len > librats::NOISE_MAX_MESSAGE_SIZE) {
92
+ LOG_DEBUG("noise", "Rejecting oversized handshake message (" << received_len << " B)");
93
+ return false;
94
+ }
95
+
96
+ uint8_t buffer[librats::NOISE_MAX_MESSAGE_SIZE];
97
+ size_t len = sizeof(buffer);
98
+ bool need_to_send = false;
99
+ const auto err = session_->handshake_step(received, received_len, buffer, &len, &need_to_send);
100
+ if (err != librats::NoiseError::OK) {
101
+ LOG_DEBUG("noise", "Handshake step failed: " << noise_error_name(err)
102
+ << " (" << (initiator_ ? "initiator" : "responder") << ")");
103
+ return false;
104
+ }
105
+ if (need_to_send) out.insert(out.end(), buffer, buffer + len);
106
+ return true;
107
+ }
108
+
109
+ std::unique_ptr<librats::NoiseSession> session_;
110
+ bool initiator_;
111
+ };
112
+
113
+ } // namespace
114
+
115
+ NoiseSecurity::NoiseSecurity(Identity identity, std::string protocol)
116
+ : identity_(identity), prologue_(protocol_id(protocol)) {}
117
+
118
+ std::unique_ptr<Handshaker> NoiseSecurity::create(ConnRole role) {
119
+ return std::make_unique<NoiseHandshaker>(identity_, role == ConnRole::Outbound, ByteView(prologue_));
120
+ }
121
+
122
+ } // namespace librats
@@ -0,0 +1,37 @@
1
+ #pragma once
2
+
3
+ /**
4
+ * @file noise_security.h
5
+ * @brief Noise_XX_25519_ChaChaPoly_SHA256 secure channel with self-certifying ids.
6
+ *
7
+ * Wraps the existing librats::NoiseSession (src/noise.h) behind the
8
+ * SecurityProvider/Handshaker/Session contract. The XX pattern mutually
9
+ * authenticates both static keys, and each side derives the other's PeerId from
10
+ * the static key it proved — so a completed handshake is also identity proof.
11
+ */
12
+
13
+ #include "librats/util/rats_export.h"
14
+ #include "librats/security/handshaker.h"
15
+ #include "librats/security/identity.h"
16
+
17
+ #include <memory>
18
+ #include <string>
19
+
20
+ namespace librats {
21
+
22
+ class RATS_API NoiseSecurity final : public SecurityProvider {
23
+ public:
24
+ /// @param protocol Application protocol id, bound into the Noise handshake
25
+ /// prologue. Peers whose protocol differs cannot complete a handshake
26
+ /// — cross-application isolation, enforced cryptographically (a
27
+ /// mismatch fails the handshake MAC). By convention "<name>/<version>".
28
+ explicit NoiseSecurity(Identity identity, std::string protocol = "librats/1.0");
29
+ std::unique_ptr<Handshaker> create(ConnRole role) override;
30
+ const PeerId& local_id() const override { return identity_.id; }
31
+
32
+ private:
33
+ Identity identity_;
34
+ std::string prologue_; ///< length-prefixed name+version, mixed into every handshake
35
+ };
36
+
37
+ } // namespace librats
@@ -0,0 +1,106 @@
1
+ #pragma once
2
+
3
+ /**
4
+ * @file plaintext_security.h
5
+ * @brief Unencrypted "secure channel": exchanges PeerIds, encrypts nothing.
6
+ *
7
+ * Useful for local/testing setups and as the trivial reference implementation
8
+ * of the SecurityProvider/Handshaker/Session contract. The handshake exchanges
9
+ * one message each way carrying the protocol id and the PeerId; the resulting
10
+ * Session is a passthrough. Note the identity here is NOT authenticated (no key
11
+ * proof) — that is the inherent trade-off of running without encryption.
12
+ *
13
+ * The protocol id is still checked (so two apps with different protocol can't
14
+ * cross-connect even unencrypted), but unlike the Noise prologue it is not
15
+ * cryptographically bound — a plaintext peer can claim any protocol. That is
16
+ * acceptable for the plaintext mode's trusted/testing use cases.
17
+ *
18
+ * Handshake message: [proto_len:u16][protocol id][peer id: 32 bytes].
19
+ */
20
+
21
+ #include "librats/security/handshaker.h"
22
+ #include "librats/security/identity.h"
23
+
24
+ #include <cstring>
25
+ #include <memory>
26
+ #include <string>
27
+
28
+ namespace librats {
29
+
30
+ /// Passthrough session: encrypt/decrypt just copy the bytes.
31
+ class PlaintextSession final : public Session {
32
+ public:
33
+ explicit PlaintextSession(PeerId remote) : remote_id_(remote) {}
34
+ bool encrypt(ByteView plain, Bytes& out) override { out.assign(plain.begin(), plain.end()); return true; }
35
+ bool decrypt(ByteView cipher, Bytes& out) override { out.assign(cipher.begin(), cipher.end()); return true; }
36
+ const PeerId& remote_id() const override { return remote_id_; }
37
+ bool is_secure() const override { return false; }
38
+ private:
39
+ PeerId remote_id_;
40
+ };
41
+
42
+ /// One-message-each exchange of [protocol id][PeerId].
43
+ class PlaintextHandshaker final : public Handshaker {
44
+ public:
45
+ PlaintextHandshaker(PeerId local, bool initiator, std::string proto)
46
+ : local_(local), proto_(std::move(proto)), initiator_(initiator) {}
47
+
48
+ bool start(Bytes& out) override {
49
+ if (initiator_) append_message(out); // initiator announces first
50
+ return true;
51
+ }
52
+
53
+ Outcome consume(ByteView incoming, Bytes& out) override {
54
+ Outcome oc;
55
+ const uint8_t* p = incoming.data();
56
+ const size_t n = incoming.size();
57
+ if (n < 2) { oc.status = Outcome::Failed; return oc; }
58
+
59
+ const size_t proto_len = (static_cast<size_t>(p[0]) << 8) | p[1];
60
+ if (n < 2 + proto_len + PeerId::kSize) { oc.status = Outcome::Failed; return oc; }
61
+
62
+ // Reject a peer announcing a different protocol id.
63
+ if (proto_len != proto_.size() ||
64
+ std::memcmp(p + 2, proto_.data(), proto_len) != 0) {
65
+ oc.status = Outcome::Failed;
66
+ return oc;
67
+ }
68
+
69
+ auto remote = PeerId::from_bytes(ByteView(p + 2 + proto_len, PeerId::kSize));
70
+ if (!remote) { oc.status = Outcome::Failed; return oc; }
71
+
72
+ if (!initiator_) append_message(out); // responder replies
73
+ oc.status = Outcome::Done;
74
+ oc.remote_id = *remote;
75
+ oc.session = std::make_unique<PlaintextSession>(*remote);
76
+ return oc;
77
+ }
78
+
79
+ private:
80
+ void append_message(Bytes& out) {
81
+ out.push_back(static_cast<uint8_t>((proto_.size() >> 8) & 0xFF));
82
+ out.push_back(static_cast<uint8_t>(proto_.size() & 0xFF));
83
+ out.insert(out.end(), proto_.begin(), proto_.end());
84
+ const auto& b = local_.bytes();
85
+ out.insert(out.end(), b.begin(), b.end());
86
+ }
87
+
88
+ PeerId local_;
89
+ std::string proto_;
90
+ bool initiator_;
91
+ };
92
+
93
+ class PlaintextSecurity final : public SecurityProvider {
94
+ public:
95
+ explicit PlaintextSecurity(Identity identity, std::string protocol = "librats/1.0")
96
+ : identity_(identity), proto_(protocol_id(protocol)) {}
97
+ std::unique_ptr<Handshaker> create(ConnRole role) override {
98
+ return std::make_unique<PlaintextHandshaker>(identity_.id, role == ConnRole::Outbound, proto_);
99
+ }
100
+ const PeerId& local_id() const override { return identity_.id; }
101
+ private:
102
+ Identity identity_;
103
+ std::string proto_;
104
+ };
105
+
106
+ } // namespace librats
@@ -0,0 +1,37 @@
1
+ #pragma once
2
+
3
+ /**
4
+ * @file session.h
5
+ * @brief Post-handshake symmetric session: encrypts/decrypts transport frames.
6
+ *
7
+ * A Session is produced by a Handshaker once the secure channel is established.
8
+ * The Connection holds it and runs every outbound frame through encrypt() and
9
+ * every inbound frame through decrypt(). The plaintext mode supplies a
10
+ * passthrough Session so the Connection code path is identical with or without
11
+ * encryption — no `if (encrypted)` scattered through the hot path.
12
+ */
13
+
14
+ #include "librats/util/rats_export.h"
15
+ #include "librats/core/bytes.h"
16
+ #include "librats/peer/peer_id.h"
17
+
18
+ namespace librats {
19
+
20
+ class RATS_API Session {
21
+ public:
22
+ virtual ~Session() = default;
23
+
24
+ /// Encrypt `plain` into `out` (resized to fit). Returns false on failure.
25
+ virtual bool encrypt(ByteView plain, Bytes& out) = 0;
26
+
27
+ /// Decrypt `cipher` into `out` (resized to fit). Returns false on failure.
28
+ virtual bool decrypt(ByteView cipher, Bytes& out) = 0;
29
+
30
+ /// The remote peer's identity, proven during the handshake.
31
+ virtual const PeerId& remote_id() const = 0;
32
+
33
+ /// True if traffic is actually encrypted (false for the plaintext passthrough).
34
+ virtual bool is_secure() const = 0;
35
+ };
36
+
37
+ } // namespace librats