librats 1.0.2 → 2.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (313) hide show
  1. package/README.md +137 -332
  2. package/binding.gyp +16 -3
  3. package/lib/index.d.ts +271 -696
  4. package/lib/index.js +383 -44
  5. package/native-src/3rdparty/android/ifaddrs-android.c +1 -0
  6. package/native-src/3rdparty/android/ifaddrs-android.h +1 -0
  7. package/native-src/CMakeLists.txt +396 -179
  8. package/native-src/LICENSE +1 -1
  9. package/native-src/src/librats/bindings/rats.cpp +731 -0
  10. package/native-src/src/librats/bindings/rats.h +352 -0
  11. package/native-src/src/librats/bittorrent/bencode.cpp +437 -0
  12. package/native-src/src/librats/bittorrent/bencode.h +176 -0
  13. package/native-src/src/librats/bittorrent/bitfield.cpp +97 -0
  14. package/native-src/src/librats/bittorrent/bitfield.h +76 -0
  15. package/native-src/src/librats/bittorrent/byte_io.h +58 -0
  16. package/native-src/src/librats/bittorrent/choker.cpp +25 -0
  17. package/native-src/src/librats/bittorrent/choker.h +46 -0
  18. package/native-src/src/librats/bittorrent/client.cpp +413 -0
  19. package/native-src/src/librats/bittorrent/client.h +227 -0
  20. package/native-src/src/librats/bittorrent/disk_io.cpp +209 -0
  21. package/native-src/src/librats/bittorrent/disk_io.h +150 -0
  22. package/native-src/src/librats/bittorrent/extensions.cpp +191 -0
  23. package/native-src/src/librats/bittorrent/extensions.h +94 -0
  24. package/native-src/src/librats/bittorrent/file_storage.cpp +77 -0
  25. package/native-src/src/librats/bittorrent/file_storage.h +79 -0
  26. package/native-src/src/librats/bittorrent/log.h +42 -0
  27. package/native-src/src/librats/bittorrent/magnet_uri.cpp +98 -0
  28. package/native-src/src/librats/bittorrent/magnet_uri.h +35 -0
  29. package/native-src/src/librats/bittorrent/peer_connection.cpp +502 -0
  30. package/native-src/src/librats/bittorrent/peer_connection.h +194 -0
  31. package/native-src/src/librats/bittorrent/peer_list.cpp +68 -0
  32. package/native-src/src/librats/bittorrent/peer_list.h +75 -0
  33. package/native-src/src/librats/bittorrent/piece_picker.cpp +352 -0
  34. package/native-src/src/librats/bittorrent/piece_picker.h +201 -0
  35. package/native-src/src/librats/bittorrent/reactor.cpp +97 -0
  36. package/native-src/src/librats/bittorrent/reactor.h +89 -0
  37. package/native-src/src/librats/bittorrent/resume_data.cpp +72 -0
  38. package/native-src/src/librats/bittorrent/resume_data.h +41 -0
  39. package/native-src/src/librats/bittorrent/store_buffer.cpp +48 -0
  40. package/native-src/src/librats/bittorrent/store_buffer.h +47 -0
  41. package/native-src/src/librats/bittorrent/torrent.cpp +870 -0
  42. package/native-src/src/librats/bittorrent/torrent.h +260 -0
  43. package/native-src/src/librats/bittorrent/torrent_creator.cpp +129 -0
  44. package/native-src/src/librats/bittorrent/torrent_creator.h +58 -0
  45. package/native-src/src/librats/bittorrent/torrent_info.cpp +314 -0
  46. package/native-src/src/librats/bittorrent/torrent_info.h +118 -0
  47. package/native-src/src/librats/bittorrent/tracker.cpp +374 -0
  48. package/native-src/src/librats/bittorrent/tracker.h +108 -0
  49. package/native-src/src/librats/bittorrent/types.cpp +206 -0
  50. package/native-src/src/librats/bittorrent/types.h +86 -0
  51. package/native-src/src/librats/core/address.cpp +35 -0
  52. package/native-src/src/librats/core/address.h +78 -0
  53. package/native-src/src/librats/core/bytes.h +69 -0
  54. package/native-src/src/librats/core/chained_send_buffer.cpp +172 -0
  55. package/native-src/src/librats/core/chained_send_buffer.h +183 -0
  56. package/native-src/src/librats/core/endpoint_parse.cpp +41 -0
  57. package/native-src/src/librats/core/endpoint_parse.h +31 -0
  58. package/native-src/src/librats/core/event_bus.h +70 -0
  59. package/native-src/src/librats/core/host_endpoint.h +56 -0
  60. package/native-src/src/{io_poller.cpp → librats/core/io_poller.cpp} +520 -65
  61. package/native-src/src/{io_poller.h → librats/core/io_poller.h} +12 -6
  62. package/native-src/src/librats/core/ip_address.cpp +120 -0
  63. package/native-src/src/librats/core/ip_address.h +109 -0
  64. package/native-src/src/librats/core/mpsc_queue.h +47 -0
  65. package/native-src/src/librats/core/notifier.h +74 -0
  66. package/native-src/src/librats/core/receive_buffer.cpp +219 -0
  67. package/native-src/src/librats/core/receive_buffer.h +171 -0
  68. package/native-src/src/librats/core/service_registry.h +58 -0
  69. package/native-src/src/{socket.cpp → librats/core/socket.cpp} +625 -118
  70. package/native-src/src/librats/core/socket.h +496 -0
  71. package/native-src/src/librats/core/timer_queue.h +105 -0
  72. package/native-src/src/librats/core/types.cpp +42 -0
  73. package/native-src/src/librats/core/types.h +93 -0
  74. package/native-src/src/librats/core/wakeup_pipe.h +83 -0
  75. package/native-src/src/{crypto → librats/crypto}/blake2_endian.h +21 -23
  76. package/native-src/src/{crypto → librats/crypto}/blake2b.c +34 -33
  77. package/native-src/src/{crypto → librats/crypto}/blake2b.h +7 -6
  78. package/native-src/src/{crypto → librats/crypto}/blake2s.c +55 -54
  79. package/native-src/src/{crypto → librats/crypto}/blake2s.h +13 -12
  80. package/native-src/src/{crypto → librats/crypto}/chacha.c +22 -21
  81. package/native-src/src/{crypto → librats/crypto}/chacha.h +14 -13
  82. package/native-src/src/{crypto → librats/crypto}/chachapoly.c +56 -56
  83. package/native-src/src/{crypto → librats/crypto}/chachapoly.h +24 -17
  84. package/native-src/src/{crc32.cpp → librats/crypto/crc32.cpp} +1 -1
  85. package/native-src/src/{crc32.h → librats/crypto/crc32.h} +3 -1
  86. package/native-src/src/{crypto → librats/crypto}/curve25519.c +6 -4
  87. package/native-src/src/{crypto → librats/crypto}/curve25519.h +6 -3
  88. package/native-src/src/librats/crypto/hkdf.c +266 -0
  89. package/native-src/src/{crypto → librats/crypto}/hkdf.h +19 -19
  90. package/native-src/src/{noise.cpp → librats/crypto/noise.cpp} +84 -73
  91. package/native-src/src/{noise.h → librats/crypto/noise.h} +18 -8
  92. package/native-src/src/{crypto → librats/crypto}/poly1305.c +47 -46
  93. package/native-src/src/librats/crypto/poly1305.h +37 -0
  94. package/native-src/src/{sha1.cpp → librats/crypto/sha1.cpp} +33 -1
  95. package/native-src/src/{sha1.h → librats/crypto/sha1.h} +14 -6
  96. package/native-src/src/{crypto → librats/crypto}/sha256.c +15 -14
  97. package/native-src/src/{crypto → librats/crypto}/sha256.h +8 -7
  98. package/native-src/src/{crypto → librats/crypto}/sha512.c +15 -14
  99. package/native-src/src/{crypto → librats/crypto}/sha512.h +8 -7
  100. package/native-src/src/librats/dht/announce.cpp +37 -0
  101. package/native-src/src/librats/dht/announce.h +41 -0
  102. package/native-src/src/librats/dht/bep42.cpp +109 -0
  103. package/native-src/src/librats/dht/bep42.h +48 -0
  104. package/native-src/src/librats/dht/dht.cpp +501 -0
  105. package/native-src/src/librats/dht/dht.h +119 -0
  106. package/native-src/src/librats/dht/dht_runner.cpp +103 -0
  107. package/native-src/src/librats/dht/dht_runner.h +71 -0
  108. package/native-src/src/librats/dht/dos_blocker.cpp +42 -0
  109. package/native-src/src/librats/dht/dos_blocker.h +47 -0
  110. package/native-src/src/librats/dht/find_peers.cpp +52 -0
  111. package/native-src/src/librats/dht/find_peers.h +73 -0
  112. package/native-src/src/librats/dht/id.h +167 -0
  113. package/native-src/src/{krpc.cpp → librats/dht/krpc.cpp} +32 -81
  114. package/native-src/src/{krpc.h → librats/dht/krpc.h} +19 -23
  115. package/native-src/src/librats/dht/log.h +38 -0
  116. package/native-src/src/librats/dht/node.cpp +473 -0
  117. package/native-src/src/librats/dht/node.h +164 -0
  118. package/native-src/src/librats/dht/node_entry.h +81 -0
  119. package/native-src/src/librats/dht/observer.h +72 -0
  120. package/native-src/src/librats/dht/persistence.cpp +90 -0
  121. package/native-src/src/librats/dht/persistence.h +32 -0
  122. package/native-src/src/librats/dht/routing_table.cpp +559 -0
  123. package/native-src/src/librats/dht/routing_table.h +185 -0
  124. package/native-src/src/librats/dht/rpc_manager.cpp +127 -0
  125. package/native-src/src/librats/dht/rpc_manager.h +77 -0
  126. package/native-src/src/librats/dht/storage.cpp +92 -0
  127. package/native-src/src/librats/dht/storage.h +74 -0
  128. package/native-src/src/librats/dht/transport.h +27 -0
  129. package/native-src/src/librats/dht/traversal.cpp +326 -0
  130. package/native-src/src/librats/dht/traversal.h +120 -0
  131. package/native-src/src/librats/dht/udp_transport.cpp +49 -0
  132. package/native-src/src/librats/dht/udp_transport.h +51 -0
  133. package/native-src/src/librats/mdns/log.h +22 -0
  134. package/native-src/src/{mdns.cpp → librats/mdns/mdns.cpp} +75 -40
  135. package/native-src/src/{mdns.h → librats/mdns/mdns.h} +9 -8
  136. package/native-src/src/{natpmp.cpp → librats/nat/natpmp.cpp} +12 -9
  137. package/native-src/src/{natpmp.h → librats/nat/natpmp.h} +3 -3
  138. package/native-src/src/{port_mapping.h → librats/nat/port_mapping.h} +3 -2
  139. package/native-src/src/{stun.cpp → librats/nat/stun.cpp} +4 -4
  140. package/native-src/src/{stun.h → librats/nat/stun.h} +1 -1
  141. package/native-src/src/{upnp.cpp → librats/nat/upnp.cpp} +6 -6
  142. package/native-src/src/{upnp.h → librats/nat/upnp.h} +2 -2
  143. package/native-src/src/librats/node/config.h +110 -0
  144. package/native-src/src/librats/node/dial_service.h +54 -0
  145. package/native-src/src/librats/node/dialer.cpp +264 -0
  146. package/native-src/src/librats/node/dialer.h +188 -0
  147. package/native-src/src/librats/node/host_events.h +26 -0
  148. package/native-src/src/librats/node/identify.cpp +130 -0
  149. package/native-src/src/librats/node/identify.h +71 -0
  150. package/native-src/src/librats/node/nat_status.cpp +103 -0
  151. package/native-src/src/librats/node/nat_status.h +118 -0
  152. package/native-src/src/librats/node/node.cpp +826 -0
  153. package/native-src/src/librats/node/node.h +333 -0
  154. package/native-src/src/librats/node/node_context.h +33 -0
  155. package/native-src/src/librats/node/peer_network.h +91 -0
  156. package/native-src/src/librats/peer/peer.h +49 -0
  157. package/native-src/src/librats/peer/peer_book.cpp +181 -0
  158. package/native-src/src/librats/peer/peer_book.h +88 -0
  159. package/native-src/src/librats/peer/peer_id.cpp +72 -0
  160. package/native-src/src/librats/peer/peer_id.h +62 -0
  161. package/native-src/src/librats/peer/peer_info.h +37 -0
  162. package/native-src/src/librats/peer/peer_table.cpp +137 -0
  163. package/native-src/src/librats/peer/peer_table.h +148 -0
  164. package/native-src/src/librats/security/handshaker.h +66 -0
  165. package/native-src/src/librats/security/identity.h +43 -0
  166. package/native-src/src/librats/security/noise_security.cpp +122 -0
  167. package/native-src/src/librats/security/noise_security.h +37 -0
  168. package/native-src/src/librats/security/plaintext_security.h +106 -0
  169. package/native-src/src/librats/security/session.h +37 -0
  170. package/native-src/src/{storage.cpp → librats/storage/storage.cpp} +369 -522
  171. package/native-src/src/{storage.h → librats/storage/storage.h} +135 -299
  172. package/native-src/src/librats/subsystems/bittorrent.cpp +211 -0
  173. package/native-src/src/librats/subsystems/bittorrent.h +136 -0
  174. package/native-src/src/librats/subsystems/dht_discovery.cpp +202 -0
  175. package/native-src/src/librats/subsystems/dht_discovery.h +123 -0
  176. package/native-src/src/librats/subsystems/dht_service.h +36 -0
  177. package/native-src/src/librats/subsystems/file_transfer.cpp +972 -0
  178. package/native-src/src/librats/subsystems/file_transfer.h +367 -0
  179. package/native-src/src/librats/subsystems/hole_punch.cpp +532 -0
  180. package/native-src/src/librats/subsystems/hole_punch.h +266 -0
  181. package/native-src/src/librats/subsystems/hole_punch_service.h +38 -0
  182. package/native-src/src/librats/subsystems/mdns_discovery.cpp +66 -0
  183. package/native-src/src/librats/subsystems/mdns_discovery.h +55 -0
  184. package/native-src/src/librats/subsystems/message_json.cpp +112 -0
  185. package/native-src/src/librats/subsystems/message_json.h +88 -0
  186. package/native-src/src/librats/subsystems/peer_exchange.cpp +241 -0
  187. package/native-src/src/librats/subsystems/peer_exchange.h +136 -0
  188. package/native-src/src/librats/subsystems/ping_service.cpp +98 -0
  189. package/native-src/src/librats/subsystems/ping_service.h +66 -0
  190. package/native-src/src/librats/subsystems/port_mapping_service.cpp +192 -0
  191. package/native-src/src/librats/subsystems/port_mapping_service.h +84 -0
  192. package/native-src/src/librats/subsystems/pubsub.cpp +567 -0
  193. package/native-src/src/librats/subsystems/pubsub.h +175 -0
  194. package/native-src/src/librats/subsystems/reconnection.cpp +239 -0
  195. package/native-src/src/librats/subsystems/reconnection.h +126 -0
  196. package/native-src/src/librats/transport/connection.cpp +343 -0
  197. package/native-src/src/librats/transport/connection.h +283 -0
  198. package/native-src/src/librats/transport/link.h +96 -0
  199. package/native-src/src/librats/transport/reactor.cpp +540 -0
  200. package/native-src/src/librats/transport/reactor.h +224 -0
  201. package/native-src/src/librats/transport/reactor_pool.h +81 -0
  202. package/native-src/src/librats/transport/tcp_link.cpp +49 -0
  203. package/native-src/src/librats/transport/tcp_link.h +43 -0
  204. package/native-src/src/librats/transport/udp_mux.cpp +617 -0
  205. package/native-src/src/librats/transport/udp_mux.h +363 -0
  206. package/native-src/src/librats/transport/udp_packet.cpp +121 -0
  207. package/native-src/src/librats/transport/udp_packet.h +190 -0
  208. package/native-src/src/librats/transport/udp_stream.cpp +1194 -0
  209. package/native-src/src/librats/transport/udp_stream.h +614 -0
  210. package/native-src/src/librats/util/features.h.in +51 -0
  211. package/native-src/src/{fs.cpp → librats/util/fs.cpp} +51 -3
  212. package/native-src/src/librats/util/fs.h +136 -0
  213. package/native-src/src/librats/util/json.cpp +1002 -0
  214. package/native-src/src/librats/util/json.h +444 -0
  215. package/native-src/src/{logger.cpp → librats/util/logger.cpp} +1 -1
  216. package/native-src/src/{logger.h → librats/util/logger.h} +43 -31
  217. package/native-src/src/{network_monitor.cpp → librats/util/network_monitor.cpp} +12 -4
  218. package/native-src/src/{network_monitor.h → librats/util/network_monitor.h} +2 -1
  219. package/native-src/src/{network_utils.cpp → librats/util/network_utils.cpp} +38 -23
  220. package/native-src/src/{network_utils.h → librats/util/network_utils.h} +15 -8
  221. package/native-src/src/{os.cpp → librats/util/os.cpp} +48 -18
  222. package/native-src/src/librats/util/rats_export.h +69 -0
  223. package/native-src/src/{version.cpp → librats/util/version.cpp} +2 -2
  224. package/native-src/src/{version.h.in → librats/util/version.h.in} +1 -1
  225. package/native-src/src/librats/wire/frame.cpp +76 -0
  226. package/native-src/src/librats/wire/frame.h +110 -0
  227. package/native-src/src/librats/wire/message_router.cpp +45 -0
  228. package/native-src/src/librats/wire/message_router.h +47 -0
  229. package/package.json +5 -4
  230. package/scripts/build-librats.js +1 -0
  231. package/scripts/postinstall.js +3 -3
  232. package/scripts/prepare-package.js +4 -4
  233. package/scripts/verify-installation.js +63 -105
  234. package/src/librats_node.cpp +1042 -1324
  235. package/native-src/src/bencode.cpp +0 -485
  236. package/native-src/src/bencode.h +0 -145
  237. package/native-src/src/bittorrent.cpp +0 -14
  238. package/native-src/src/bittorrent.h +0 -74
  239. package/native-src/src/bt_bitfield.cpp +0 -372
  240. package/native-src/src/bt_bitfield.h +0 -316
  241. package/native-src/src/bt_choker.cpp +0 -228
  242. package/native-src/src/bt_choker.h +0 -147
  243. package/native-src/src/bt_client.cpp +0 -1047
  244. package/native-src/src/bt_client.h +0 -445
  245. package/native-src/src/bt_create_torrent.cpp +0 -677
  246. package/native-src/src/bt_create_torrent.h +0 -473
  247. package/native-src/src/bt_extension.cpp +0 -469
  248. package/native-src/src/bt_extension.h +0 -309
  249. package/native-src/src/bt_file_storage.cpp +0 -261
  250. package/native-src/src/bt_file_storage.h +0 -298
  251. package/native-src/src/bt_handshake.cpp +0 -134
  252. package/native-src/src/bt_handshake.h +0 -157
  253. package/native-src/src/bt_messages.cpp +0 -364
  254. package/native-src/src/bt_messages.h +0 -324
  255. package/native-src/src/bt_network.cpp +0 -1007
  256. package/native-src/src/bt_network.h +0 -417
  257. package/native-src/src/bt_peer_connection.cpp +0 -742
  258. package/native-src/src/bt_peer_connection.h +0 -592
  259. package/native-src/src/bt_piece_picker.cpp +0 -786
  260. package/native-src/src/bt_piece_picker.h +0 -473
  261. package/native-src/src/bt_resume_data.cpp +0 -410
  262. package/native-src/src/bt_resume_data.h +0 -249
  263. package/native-src/src/bt_torrent.cpp +0 -2120
  264. package/native-src/src/bt_torrent.h +0 -641
  265. package/native-src/src/bt_torrent_info.cpp +0 -659
  266. package/native-src/src/bt_torrent_info.h +0 -418
  267. package/native-src/src/bt_types.h +0 -621
  268. package/native-src/src/chained_send_buffer.cpp +0 -75
  269. package/native-src/src/chained_send_buffer.h +0 -137
  270. package/native-src/src/crypto/hkdf.c +0 -266
  271. package/native-src/src/crypto/poly1305.h +0 -36
  272. package/native-src/src/dht.cpp +0 -3311
  273. package/native-src/src/dht.h +0 -717
  274. package/native-src/src/disk_io.cpp +0 -632
  275. package/native-src/src/disk_io.h +0 -315
  276. package/native-src/src/file_transfer.cpp +0 -1415
  277. package/native-src/src/file_transfer.h +0 -286
  278. package/native-src/src/fs.h +0 -108
  279. package/native-src/src/gossipsub.cpp +0 -1139
  280. package/native-src/src/gossipsub.h +0 -403
  281. package/native-src/src/ice.cpp +0 -893
  282. package/native-src/src/ice.h +0 -559
  283. package/native-src/src/json.hpp +0 -25526
  284. package/native-src/src/librats.cpp +0 -2378
  285. package/native-src/src/librats.h +0 -2324
  286. package/native-src/src/librats_bittorrent.cpp +0 -601
  287. package/native-src/src/librats_c.cpp +0 -1557
  288. package/native-src/src/librats_c.h +0 -323
  289. package/native-src/src/librats_discovery.cpp +0 -402
  290. package/native-src/src/librats_encryption.cpp +0 -275
  291. package/native-src/src/librats_file_transfer.cpp +0 -144
  292. package/native-src/src/librats_gossipsub.cpp +0 -289
  293. package/native-src/src/librats_ice.cpp +0 -213
  294. package/native-src/src/librats_log_macros.h +0 -36
  295. package/native-src/src/librats_logging.cpp +0 -173
  296. package/native-src/src/librats_mdns.cpp +0 -166
  297. package/native-src/src/librats_persistence.cpp +0 -796
  298. package/native-src/src/librats_portmap.cpp +0 -419
  299. package/native-src/src/librats_reconnection.cpp +0 -218
  300. package/native-src/src/librats_statistic.cpp +0 -105
  301. package/native-src/src/librats_storage.cpp +0 -189
  302. package/native-src/src/rats_export.h +0 -17
  303. package/native-src/src/receive_buffer.cpp +0 -82
  304. package/native-src/src/receive_buffer.h +0 -127
  305. package/native-src/src/socket.h +0 -228
  306. package/native-src/src/threadmanager.cpp +0 -105
  307. package/native-src/src/threadmanager.h +0 -53
  308. package/native-src/src/tracker.cpp +0 -1264
  309. package/native-src/src/tracker.h +0 -319
  310. package/native-src/src/turn.cpp +0 -762
  311. package/native-src/src/turn.h +0 -460
  312. package/native-src/src/wakeup_pipe.h +0 -60
  313. /package/native-src/src/{os.h → librats/util/os.h} +0 -0
@@ -0,0 +1,224 @@
1
+ #pragma once
2
+
3
+ /**
4
+ * @file reactor.h
5
+ * @brief Single-threaded I/O reactor owning a shard of connections.
6
+ *
7
+ * A Reactor runs one thread that drives an IOPoller and owns every Connection
8
+ * assigned to it. ALL connection state lives behind this one thread, so the
9
+ * data path has zero locks. Other threads interact with it only by:
10
+ *
11
+ * - post(task) — run a closure on the reactor thread (wakes it);
12
+ * - execute(task) — same, but runs inline if already on the reactor thread;
13
+ * - connect()/close() — convenience wrappers that post the right task.
14
+ *
15
+ * The single synchronisation point is the MPSC task queue plus a WakeupPipe to
16
+ * interrupt the poll wait. Timers (handshake timeouts, backoff) ride on the same
17
+ * loop via a TimerQueue that also sizes each poll wait.
18
+ *
19
+ * ── Two transports, one loop ────────────────────────────────────────────────
20
+ * Connections are keyed by ConnId, not by socket, because only one of the two
21
+ * transports has a socket per connection:
22
+ *
23
+ * - TCP: one kernel socket per peer, registered with the poller. A poll event
24
+ * names a socket, which the fd → ConnId map turns into a connection.
25
+ * - UDP: every peer shares one socket, owned by the UdpMux. A poll event on it
26
+ * means "datagrams arrived"; the mux routes them to streams by connection id
27
+ * and hands back the same readable/writable/error events the poller would
28
+ * have produced. From dispatch_events() down, the two are indistinguishable.
29
+ *
30
+ * Both listeners are optional and independent: a reactor can accept TCP, accept
31
+ * UDP, both, or neither (dial-only). Only the reactor that owns the mux can dial
32
+ * over UDP, which is why the pool routes UDP dials to it (see reactor_pool.h).
33
+ *
34
+ * A ReactorPool (see reactor_pool.h) runs N of these and shards connections
35
+ * across them; with N == 1 this is a classic single-threaded reactor.
36
+ */
37
+
38
+ #include "librats/core/types.h"
39
+ #include "librats/transport/connection.h"
40
+ #include "librats/transport/udp_mux.h"
41
+ #include "librats/core/mpsc_queue.h"
42
+ #include "librats/core/timer_queue.h"
43
+ #include "librats/core/io_poller.h"
44
+ #include "librats/core/notifier.h"
45
+ #include "librats/core/socket.h"
46
+
47
+ #include <atomic>
48
+ #include <chrono>
49
+ #include <functional>
50
+ #include <memory>
51
+ #include <string>
52
+ #include <thread>
53
+ #include <unordered_map>
54
+ #include <unordered_set>
55
+ #include <vector>
56
+
57
+ namespace librats {
58
+
59
+ class Reactor final : public UdpMuxDelegate {
60
+ public:
61
+ using Task = std::function<void()>;
62
+
63
+ /// @param index This reactor's slot in its pool (for sharding/logging).
64
+ /// @param delegate Sink for all connection lifecycle/frame events.
65
+ /// @param security Mints a Handshaker per connection (Noise / plaintext).
66
+ Reactor(uint8_t index, ConnectionDelegate& delegate, SecurityProvider& security);
67
+ ~Reactor() override;
68
+
69
+ Reactor(const Reactor&) = delete;
70
+ Reactor& operator=(const Reactor&) = delete;
71
+
72
+ /// Adopt an already-bound, listening TCP socket. Call before start().
73
+ void listen(socket_t server_socket);
74
+
75
+ /// Adopt an already-bound UDP socket and run the datagram transport on it.
76
+ /// Call before start(). This is what makes the reactor able to accept *and*
77
+ /// dial over UDP; without it, UDP dials are refused.
78
+ void listen_udp(socket_t udp_socket, AddressFamily family);
79
+
80
+ /// Whether this reactor can carry UDP connections (i.e. it owns the mux).
81
+ bool has_udp() const noexcept { return mux_ != nullptr; }
82
+
83
+ void start(); ///< spawn the reactor thread
84
+ void stop(); ///< signal shutdown and join; closes all connections
85
+
86
+ // — cross-thread work submission —
87
+ void post(Task task); ///< enqueue + wake (any thread)
88
+ void execute(Task task); ///< inline if on-thread, else post()
89
+ bool on_reactor_thread() const noexcept;
90
+
91
+ /// Begin a non-blocking outbound connection over `kind` (thread-safe).
92
+ ///
93
+ /// Returns the ConnId the connection *will* have, reserved synchronously so a
94
+ /// caller can cancel the attempt with cancel_dial() before it has even started
95
+ /// — which is what lets the node race a UDP dial against a TCP one and drop the
96
+ /// loser cleanly. kInvalidConnId if the transport is unavailable here.
97
+ ///
98
+ /// `profile` shapes how hard a datagram dial retries its Syn (see DialProfile);
99
+ /// it has no meaning for TCP, where the kernel owns the connect retries.
100
+ ConnId connect(std::string host, int port, TransportKind kind = TransportKind::Tcp,
101
+ DialProfile profile = {});
102
+
103
+ /// Close a connection by id (thread-safe; deferred to the reactor thread).
104
+ /// Valid for an id whose dial has not started yet — it is cancelled instead.
105
+ void close(ConnId id, CloseReason reason);
106
+
107
+ /// Drop a dial that lost its race — but only while it is still a dial. Once an
108
+ /// attempt has established it is not an attempt any more, it is one of possibly
109
+ /// several links to a peer, and which of those survives is the peer table's
110
+ /// call, made identically at both ends. The check happens here because this is
111
+ /// the one thread that can read the connection's state without racing it.
112
+ void cancel_dial(ConnId id, CloseReason reason);
113
+
114
+ /// Send a frame to every Established connection on this reactor. Thread-safe:
115
+ /// the iteration runs on the reactor thread. The payload is shared across
116
+ /// connections (the per-peer encryption still happens in each Connection).
117
+ void broadcast(FrameHeader header, std::shared_ptr<const Bytes> payload);
118
+
119
+ // — timers (reactor thread, or via post/execute) —
120
+ TimerId schedule(std::chrono::milliseconds delay, Task on_fire);
121
+ void cancel(TimerId id);
122
+
123
+ /// Look up an owned connection. Reactor thread only.
124
+ Connection* find(ConnId id) noexcept;
125
+
126
+ /// Adjust poll interest for a socket. Called by TcpLink; reactor thread.
127
+ void set_interest(socket_t sock, uint32_t events);
128
+
129
+ /// Book a flush for the end of this turn: `id` has frames queued that have
130
+ /// not been written yet. Called by Connection::send, which aggregates rather
131
+ /// than writing through — see the note there. Reactor thread; each connection
132
+ /// books at most one flush per turn.
133
+ void mark_dirty(ConnId id) { dirty_.push_back(id); }
134
+
135
+ /// The security provider used to mint per-connection handshakers.
136
+ SecurityProvider& security() noexcept { return security_; }
137
+
138
+ /// Approximate live connection count (lock-free, eventually consistent).
139
+ size_t connection_count() const noexcept {
140
+ return conn_count_.load(std::memory_order_relaxed);
141
+ }
142
+
143
+ uint8_t index() const noexcept { return index_; }
144
+
145
+ private:
146
+ // — UdpMuxDelegate —
147
+ ConnId adopt_inbound_link(std::unique_ptr<Link> link) override;
148
+ void dispatch_link_events(ConnId id, uint32_t events) override;
149
+
150
+ void run();
151
+ void drain_tasks(std::vector<Task>& scratch);
152
+ void drain_wakeup();
153
+ void handle_event(const PollResult& ev);
154
+ void dispatch_events(ConnId id, uint32_t events);
155
+ void do_accept();
156
+ void schedule_maintenance();
157
+ void start_dial(ConnId id, const std::string& host, int port, TransportKind kind,
158
+ DialProfile profile);
159
+ void abort_dial(ConnId id, const std::string& host, int port);
160
+ Connection* adopt(std::unique_ptr<Link> link, ConnRole role, ConnId id);
161
+ bool resolve_dial(ConnId id);
162
+ /// Body of close()/cancel_dial(); `spare_established` makes it a no-op for a
163
+ /// connection that has already finished its handshake.
164
+ void close_conn(ConnId id, CloseReason reason, bool spare_established);
165
+ void mark_for_close(ConnId id, CloseReason reason);
166
+ void process_pending_close();
167
+ void flush_dirty(); ///< write out what send() queued this turn
168
+ void remove(ConnId id, CloseReason reason);
169
+ void shutdown_connections();
170
+
171
+ static constexpr int kMaxEvents = 256;
172
+ // Idle poll cap. Kept short as a stopgap for an IOCP quirk: connecting
173
+ // sockets live in WSAPoll-fallback mode and are only re-checked once per
174
+ // wait() iteration, so connect-completion latency is bounded by this value.
175
+ // Negligible idle cost; on epoll/kqueue the loop still wakes on real events,
176
+ // so this only caps idle latency.
177
+ static constexpr int kMaxPollMs = 50;
178
+ /// Deadline from adopt() to reaching Established (covers connect + handshake).
179
+ static constexpr std::chrono::milliseconds kEstablishTimeout{15000};
180
+ /// Cadence of the housekeeping sweep over this reactor's connections (currently
181
+ /// only Connection::on_maintenance_tick, which ages idle receive buffers). One
182
+ /// timer per reactor rather than one per connection: the work is a few pointer
183
+ /// comparisons per peer, so a sweep is cheaper than N timer entries.
184
+ static constexpr std::chrono::milliseconds kMaintenanceInterval{10000};
185
+
186
+ uint8_t index_;
187
+ ConnectionDelegate& delegate_;
188
+ SecurityProvider& security_;
189
+ std::unique_ptr<IOPoller> poller_;
190
+ Notifier wakeup_;
191
+ MpscQueue<Task> tasks_;
192
+ TimerQueue timers_;
193
+
194
+ // Declared before conns_ so it is destroyed *after* them: every UDP
195
+ // connection's Link points into the mux and tells it, on destruction, that its
196
+ // stream may go. Reversing these two would have that run against freed memory.
197
+ std::unique_ptr<UdpMux> mux_;
198
+
199
+ // Connections are keyed by their stable ConnId, since a UDP connection has no
200
+ // socket of its own; fd_to_conn_ maps the sockets that do exist (TCP, and the
201
+ // listener) back to that key for poll dispatch.
202
+ std::unordered_map<ConnId, std::unique_ptr<Connection>> conns_;
203
+ std::unordered_map<socket_t, ConnId> fd_to_conn_;
204
+ std::unordered_map<ConnId, CloseReason> pending_close_;
205
+ /// Connections with frames queued but not yet written this turn. Holds ids,
206
+ /// not pointers, so a connection torn down in between is simply not found.
207
+ std::vector<ConnId> dirty_;
208
+ /// Dials cancelled before their connect task ran (see connect()/close()).
209
+ std::unordered_set<ConnId> cancelled_dials_;
210
+ /// Highest ConnId that has already been adopted or abandoned; anything at or
211
+ /// below it has resolved, so a late close() for it needs no cancellation slot.
212
+ ConnId resolved_watermark_ = 0;
213
+
214
+ socket_t server_socket_ = RATS_INVALID_SOCKET;
215
+ std::atomic<ConnId> next_conn_id_{1};
216
+ std::atomic<size_t> conn_count_{0};
217
+ std::atomic<bool> running_{false};
218
+ std::thread thread_;
219
+ // Published with release by the reactor thread in run(), read with acquire by
220
+ // any thread in on_reactor_thread(); plain access would be a data race.
221
+ std::atomic<std::thread::id> thread_id_{};
222
+ };
223
+
224
+ } // namespace librats
@@ -0,0 +1,81 @@
1
+ #pragma once
2
+
3
+ /**
4
+ * @file reactor_pool.h
5
+ * @brief A fixed set of reactors; connections are sharded across them.
6
+ *
7
+ * Default size 1 — a single reactor, which is plenty for thousands of peers.
8
+ * Larger pools shard outbound connections round-robin; because each Connection
9
+ * is pinned to one reactor for life, nothing on the data path needs to change as
10
+ * the pool grows. (Sharding *inbound* connections across reactors — handing an
11
+ * accepted fd to a non-acceptor reactor — is a future enhancement; for now a
12
+ * single reactor accepts and owns inbound connections.)
13
+ *
14
+ * UDP is a deliberate exception to the round-robin. Every UDP connection shares
15
+ * one socket — that is the point of it — so the mux, and therefore every stream
16
+ * on it, belongs to the single reactor that owns that socket. Sharding those
17
+ * across threads would mean handing datagrams between reactors on every packet,
18
+ * which costs more than the parallelism buys. pick() honours that by routing UDP
19
+ * dials to the mux's reactor and everything else round-robin.
20
+ */
21
+
22
+ #include "librats/transport/reactor.h"
23
+
24
+ #include <atomic>
25
+ #include <cstdint>
26
+ #include <memory>
27
+ #include <vector>
28
+
29
+ namespace librats {
30
+
31
+ class ReactorPool {
32
+ public:
33
+ ReactorPool(size_t count, ConnectionDelegate& delegate, SecurityProvider& security) {
34
+ if (count == 0) count = 1;
35
+ reactors_.reserve(count);
36
+ for (size_t i = 0; i < count; ++i)
37
+ reactors_.push_back(std::make_unique<Reactor>(static_cast<uint8_t>(i), delegate, security));
38
+ }
39
+
40
+ /// Hand the listening socket to the acceptor reactor (index 0). Before start().
41
+ void listen(socket_t server_socket) { reactors_[0]->listen(server_socket); }
42
+
43
+ /// Hand the shared UDP socket to the acceptor reactor (index 0), which then
44
+ /// owns every datagram connection. Before start().
45
+ void listen_udp(socket_t udp_socket, AddressFamily family) {
46
+ reactors_[0]->listen_udp(udp_socket, family);
47
+ }
48
+
49
+ /// Whether the pool can carry UDP connections at all.
50
+ bool has_udp() const noexcept { return reactors_[0]->has_udp(); }
51
+
52
+ void start() { for (auto& r : reactors_) r->start(); }
53
+ void stop() { for (auto& r : reactors_) r->stop(); }
54
+
55
+ size_t size() const noexcept { return reactors_.size(); }
56
+ Reactor& by_index(uint8_t i) noexcept { return *reactors_[i]; }
57
+
58
+ /// Choose a reactor for a new outbound connection over `kind`. UDP always
59
+ /// lands on the reactor that owns the socket it must go out on; anything else
60
+ /// is spread round-robin.
61
+ Reactor& pick(TransportKind kind = TransportKind::Tcp) noexcept {
62
+ if (kind == TransportKind::Udp) return *reactors_[0];
63
+ const size_t i = next_.fetch_add(1, std::memory_order_relaxed) % reactors_.size();
64
+ return *reactors_[i];
65
+ }
66
+
67
+ template <typename F>
68
+ void for_each(F&& fn) { for (auto& r : reactors_) fn(*r); }
69
+
70
+ size_t connection_count() const noexcept {
71
+ size_t total = 0;
72
+ for (const auto& r : reactors_) total += r->connection_count();
73
+ return total;
74
+ }
75
+
76
+ private:
77
+ std::vector<std::unique_ptr<Reactor>> reactors_;
78
+ std::atomic<size_t> next_{0};
79
+ };
80
+
81
+ } // namespace librats
@@ -0,0 +1,49 @@
1
+ #include "librats/transport/tcp_link.h"
2
+ #include "librats/transport/reactor.h"
3
+ #include "librats/core/io_poller.h"
4
+
5
+ #include <cerrno>
6
+
7
+ namespace librats {
8
+
9
+ namespace {
10
+
11
+ #ifdef _WIN32
12
+ inline bool last_error_would_block() { return WSAGetLastError() == WSAEWOULDBLOCK; }
13
+ #else
14
+ inline bool last_error_would_block() { return errno == EAGAIN || errno == EWOULDBLOCK; }
15
+ #endif
16
+
17
+ } // namespace
18
+
19
+ Link::IoResult TcpLink::read(ByteSpan into) {
20
+ const int n = ::recv(socket_, reinterpret_cast<char*>(into.data()),
21
+ static_cast<int>(into.size()), 0);
22
+ if (n > 0) return {static_cast<size_t>(n), Status::Ok};
23
+ if (n == 0) return {0, Status::Closed}; // FIN: the peer is done sending
24
+ return {0, last_error_would_block() ? Status::WouldBlock : Status::Error};
25
+ }
26
+
27
+ Link::IoResult TcpLink::write(const ByteView* slices, size_t count) {
28
+ const std::ptrdiff_t n = send_vectored(socket_, slices, count);
29
+ if (n > 0) return {static_cast<size_t>(n), Status::Ok};
30
+ // n == 0 means the socket accepted nothing this round — indistinguishable from
31
+ // a full send buffer as far as the caller is concerned, so report would-block
32
+ // and let the next writable event drive the retry.
33
+ if (n == 0) return {0, Status::WouldBlock};
34
+ return {0, last_error_would_block() ? Status::WouldBlock : Status::Error};
35
+ }
36
+
37
+ bool TcpLink::connect_completed() {
38
+ return tcp_connect_result(socket_) == 0;
39
+ }
40
+
41
+ void TcpLink::want_write(bool on) {
42
+ reactor_.set_interest(socket_, on ? (PollIn | PollOut) : static_cast<uint32_t>(PollIn));
43
+ }
44
+
45
+ std::optional<Address> TcpLink::remote_endpoint() const {
46
+ return get_peer_endpoint(socket_);
47
+ }
48
+
49
+ } // namespace librats
@@ -0,0 +1,43 @@
1
+ #pragma once
2
+
3
+ /**
4
+ * @file tcp_link.h
5
+ * @brief Link over a kernel TCP socket — the thin, obvious implementation.
6
+ *
7
+ * All of the reliability, ordering and congestion control a Link promises is the
8
+ * kernel's job here, so this is a direct translation of recv/sendmsg semantics
9
+ * into the Link vocabulary. The socket is owned by the Reactor (which registers
10
+ * it with the poller and closes it on teardown), not by the link.
11
+ */
12
+
13
+ #include "librats/transport/link.h"
14
+
15
+ namespace librats {
16
+
17
+ class Reactor;
18
+
19
+ class TcpLink final : public Link {
20
+ public:
21
+ TcpLink(socket_t sock, Reactor& reactor) : socket_(sock), reactor_(reactor) {}
22
+
23
+ TransportKind kind() const noexcept override { return TransportKind::Tcp; }
24
+
25
+ IoResult read(ByteSpan into) override;
26
+ IoResult write(const ByteView* slices, size_t count) override;
27
+ bool connect_completed() override;
28
+ void want_write(bool on) override;
29
+
30
+ std::optional<Address> remote_endpoint() const override;
31
+
32
+ socket_t fd() const noexcept override { return socket_; }
33
+
34
+ /// TCP needs no goodbye of its own: the Reactor closes the socket right after,
35
+ /// which sends the FIN. (A CloseReason has no place on the wire here.)
36
+ void close(CloseReason) override {}
37
+
38
+ private:
39
+ socket_t socket_;
40
+ Reactor& reactor_;
41
+ };
42
+
43
+ } // namespace librats