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,89 @@
1
+ #pragma once
2
+
3
+ /**
4
+ * @file reactor.h
5
+ * @brief Single-threaded event loop for the BitTorrent peer transport.
6
+ *
7
+ * BitTorrent peers speak a plaintext wire protocol that is unrelated to the
8
+ * node's Noise mesh, so rather than bend `transport::Reactor` (which is tied to
9
+ * the Noise handshake) we assemble a dedicated loop from the same reusable
10
+ * primitives: an IOPoller, a TimerQueue, an MPSC task queue and a Notifier
11
+ * self-pipe to break the poll wait.
12
+ *
13
+ * One thread owns the loop and therefore all protocol state hung off it — peers,
14
+ * pickers, torrents — so none of that needs locks. Other threads reach in only
15
+ * through post(), which enqueues a task and wakes the loop. Socket registration
16
+ * (add/modify/remove) and timers are reactor-thread-only; call them from a task
17
+ * if you are elsewhere.
18
+ */
19
+
20
+ #include "librats/util/rats_export.h"
21
+ #include "librats/core/io_poller.h"
22
+ #include "librats/core/mpsc_queue.h"
23
+ #include "librats/core/notifier.h"
24
+ #include "librats/core/socket.h"
25
+ #include "librats/core/timer_queue.h"
26
+ #include "librats/core/types.h"
27
+
28
+ #include <atomic>
29
+ #include <chrono>
30
+ #include <cstdint>
31
+ #include <functional>
32
+ #include <thread>
33
+ #include <unordered_map>
34
+
35
+ namespace librats::bittorrent {
36
+
37
+ class RATS_API Reactor {
38
+ public:
39
+ using Task = std::function<void()>;
40
+ using IoCallback = std::function<void(std::uint32_t events)>;
41
+ using TimerCallback = std::function<void()>;
42
+
43
+ Reactor();
44
+ ~Reactor();
45
+
46
+ Reactor(const Reactor&) = delete;
47
+ Reactor& operator=(const Reactor&) = delete;
48
+
49
+ /// Run the loop on a dedicated thread until stop().
50
+ void start();
51
+ /// Stop the loop and join its thread (if any). Idempotent.
52
+ void stop();
53
+ /// Run the loop on the calling thread until stop().
54
+ void run();
55
+ /// Run a single loop iteration: poll, dispatch I/O, run posted tasks and due
56
+ /// timers. Exposed for tests and for embedding in another loop.
57
+ void run_one(int timeout_ms);
58
+
59
+ bool running() const noexcept { return running_.load(); }
60
+ bool on_reactor_thread() const noexcept { return std::this_thread::get_id() == loop_thread_; }
61
+
62
+ /// Enqueue a task to run on the reactor thread. Thread-safe.
63
+ void post(Task task);
64
+
65
+ // ---- reactor-thread only ----
66
+ bool add(socket_t fd, std::uint32_t events, IoCallback cb);
67
+ bool modify(socket_t fd, std::uint32_t events);
68
+ void remove(socket_t fd);
69
+
70
+ TimerId schedule(std::chrono::milliseconds delay, TimerCallback cb);
71
+ void cancel(TimerId id);
72
+
73
+ private:
74
+ void dispatch_io();
75
+ void run_tasks();
76
+
77
+ std::unique_ptr<IOPoller> poller_;
78
+ TimerQueue timers_;
79
+ MpscQueue<Task> tasks_;
80
+ Notifier notifier_;
81
+ std::unordered_map<socket_t, IoCallback> handlers_;
82
+ std::vector<Task> task_scratch_;
83
+
84
+ std::atomic<bool> running_{false};
85
+ std::thread thread_;
86
+ std::thread::id loop_thread_;
87
+ };
88
+
89
+ } // namespace librats::bittorrent
@@ -0,0 +1,72 @@
1
+ #include "librats/bittorrent/resume_data.h"
2
+
3
+ #include "librats/bittorrent/bencode.h"
4
+
5
+ #include <cstring>
6
+
7
+ namespace librats::bittorrent {
8
+
9
+ namespace {
10
+ constexpr char kFormatTag[] = "librats resume";
11
+
12
+ const librats::BencodeValue* find(const librats::BencodeValue& d, const char* key) {
13
+ return d.find(key);
14
+ }
15
+ } // namespace
16
+
17
+ Bytes ResumeData::encode() const {
18
+ librats::BencodeValue d = librats::BencodeValue::create_dict();
19
+ d["format"] = librats::BencodeValue(std::string(kFormatTag));
20
+ d["version"] = librats::BencodeValue(std::int64_t(1));
21
+ d["info-hash"] = librats::BencodeValue(std::string(reinterpret_cast<const char*>(info_hash.data()), info_hash.size()));
22
+ d["name"] = librats::BencodeValue(name);
23
+ d["save-path"] = librats::BencodeValue(save_path);
24
+ d["num-pieces"] = librats::BencodeValue(std::int64_t(have.size()));
25
+ d["pieces"] = librats::BencodeValue(std::string(reinterpret_cast<const char*>(have.data()), have.data_size()));
26
+ d["uploaded"] = librats::BencodeValue(std::int64_t(total_uploaded));
27
+ d["downloaded"] = librats::BencodeValue(std::int64_t(total_downloaded));
28
+ if (!info_dict.empty())
29
+ d["info"] = librats::BencodeValue(std::string(reinterpret_cast<const char*>(info_dict.data()), info_dict.size()));
30
+ return d.encode();
31
+ }
32
+
33
+ std::optional<ResumeData> ResumeData::decode(const Bytes& data) {
34
+ try {
35
+ librats::BencodeValue d = librats::BencodeDecoder::decode(data.data(), data.size());
36
+ if (!d.is_dict()) return std::nullopt;
37
+ const auto* fmt = find(d, "format");
38
+ if (!fmt || !fmt->is_string() || fmt->as_string() != kFormatTag) return std::nullopt;
39
+
40
+ ResumeData rd;
41
+ if (const auto* ih = find(d, "info-hash"); ih && ih->is_string() && ih->as_string().size() == 20)
42
+ std::memcpy(rd.info_hash.data(), ih->as_string().data(), 20);
43
+ if (const auto* n = find(d, "name"); n && n->is_string()) rd.name = n->as_string();
44
+ if (const auto* sp = find(d, "save-path"); sp && sp->is_string()) rd.save_path = sp->as_string();
45
+ if (const auto* up = find(d, "uploaded"); up && up->is_integer()) rd.total_uploaded = std::uint64_t(up->as_integer());
46
+ if (const auto* dn = find(d, "downloaded"); dn && dn->is_integer()) rd.total_downloaded = std::uint64_t(dn->as_integer());
47
+
48
+ std::int64_t num_pieces = 0;
49
+ if (const auto* np = find(d, "num-pieces"); np && np->is_integer() && np->as_integer() >= 0)
50
+ num_pieces = np->as_integer();
51
+ if (const auto* p = find(d, "pieces"); p && p->is_string()) {
52
+ const std::string& bytes = p->as_string();
53
+ // `num-pieces` is attacker-controlled and drives Bitfield::assign's
54
+ // allocation independently of the `pieces` string length. A tiny file
55
+ // claiming billions of pieces would allocate gigabytes (C4). A valid
56
+ // record always has exactly ceil(num_pieces/8) bytes of bitfield, so
57
+ // reject anything that doesn't match rather than trusting the count.
58
+ if (std::uint64_t((num_pieces + 7) / 8) != bytes.size()) return std::nullopt;
59
+ rd.have.assign(reinterpret_cast<const std::uint8_t*>(bytes.data()),
60
+ bytes.size(), std::size_t(num_pieces));
61
+ }
62
+
63
+ if (const auto* info = find(d, "info"); info && info->is_string())
64
+ rd.info_dict.assign(info->as_string().begin(), info->as_string().end());
65
+
66
+ return rd;
67
+ } catch (const std::exception&) {
68
+ return std::nullopt;
69
+ }
70
+ }
71
+
72
+ } // namespace librats::bittorrent
@@ -0,0 +1,41 @@
1
+ #pragma once
2
+
3
+ /**
4
+ * @file resume_data.h
5
+ * @brief Fast-resume state: what a torrent needs to pick up where it left off
6
+ * without re-hashing every piece on disk.
7
+ *
8
+ * It is a small bencoded record — the have-bitfield, transfer totals, save path
9
+ * and (optionally) the verbatim info dictionary so a magnet-started torrent can
10
+ * resume without re-fetching metadata. On load the engine *trusts* the recorded
11
+ * bitfield (skipping the hash check for those pieces); the verbatim info section,
12
+ * if present, is re-hashed against the info-hash before it is believed.
13
+ */
14
+
15
+ #include "librats/util/rats_export.h"
16
+ #include "librats/bittorrent/bitfield.h"
17
+ #include "librats/bittorrent/types.h"
18
+ #include "librats/core/bytes.h"
19
+
20
+ #include <cstdint>
21
+ #include <optional>
22
+ #include <string>
23
+
24
+ namespace librats::bittorrent {
25
+
26
+ struct RATS_API ResumeData {
27
+ InfoHash info_hash{};
28
+ std::string name;
29
+ std::string save_path;
30
+ Bitfield have; ///< pieces already on disk
31
+ std::uint64_t total_uploaded = 0;
32
+ std::uint64_t total_downloaded = 0;
33
+ Bytes info_dict; ///< optional verbatim info section
34
+
35
+ /// Serialise to the on-disk bencoded form.
36
+ Bytes encode() const;
37
+ /// Parse it back. nullopt if it isn't a librats resume record.
38
+ static std::optional<ResumeData> decode(const Bytes& data);
39
+ };
40
+
41
+ } // namespace librats::bittorrent
@@ -0,0 +1,48 @@
1
+ #include "librats/bittorrent/store_buffer.h"
2
+
3
+ #include <algorithm>
4
+
5
+ namespace librats::bittorrent {
6
+
7
+ void StoreBuffer::insert(std::uint32_t piece, std::uint32_t offset, const Bytes& data) {
8
+ std::lock_guard<std::mutex> lock(mutex_);
9
+ blocks_[{piece, offset}] = data;
10
+ }
11
+
12
+ void StoreBuffer::erase(std::uint32_t piece, std::uint32_t offset) {
13
+ std::lock_guard<std::mutex> lock(mutex_);
14
+ blocks_.erase({piece, offset});
15
+ }
16
+
17
+ void StoreBuffer::overlay(std::uint32_t piece, std::uint32_t offset, Bytes& out) const {
18
+ if (out.empty()) return;
19
+ const std::uint64_t read_begin = offset;
20
+ const std::uint64_t read_end = offset + out.size();
21
+
22
+ std::lock_guard<std::mutex> lock(mutex_);
23
+ // Walk only this piece's entries: keys in [(piece,0), (piece+1,0)).
24
+ auto it = blocks_.lower_bound({piece, 0});
25
+ auto end = (piece == UINT32_MAX) ? blocks_.end() : blocks_.lower_bound({piece + 1, 0});
26
+ for (; it != end; ++it) {
27
+ const std::uint64_t blk_begin = it->first.second;
28
+ const std::uint64_t blk_end = blk_begin + it->second.size();
29
+ const std::uint64_t from = (std::max)(read_begin, blk_begin);
30
+ const std::uint64_t to = (std::min)(read_end, blk_end);
31
+ if (from >= to) continue; // no intersection
32
+ std::copy(it->second.begin() + std::ptrdiff_t(from - blk_begin),
33
+ it->second.begin() + std::ptrdiff_t(to - blk_begin),
34
+ out.begin() + std::ptrdiff_t(from - read_begin));
35
+ }
36
+ }
37
+
38
+ bool StoreBuffer::empty() const {
39
+ std::lock_guard<std::mutex> lock(mutex_);
40
+ return blocks_.empty();
41
+ }
42
+
43
+ std::size_t StoreBuffer::size() const {
44
+ std::lock_guard<std::mutex> lock(mutex_);
45
+ return blocks_.size();
46
+ }
47
+
48
+ } // namespace librats::bittorrent
@@ -0,0 +1,47 @@
1
+ #pragma once
2
+
3
+ /**
4
+ * @file store_buffer.h
5
+ * @brief In-RAM cache of blocks whose disk write is still in flight.
6
+ *
7
+ * When a block is handed to the disk for writing it is also parked here, keyed
8
+ * by (piece, offset within piece). A read or hash issued before that write
9
+ * reaches the platter is then satisfied from RAM by overlaying these bytes onto
10
+ * whatever the disk returned — so the engine never reads stale data for a block
11
+ * it has already accepted. The entry is dropped once the write completes.
12
+ *
13
+ * Thread-safe: writers insert/erase from disk-worker threads while readers
14
+ * overlay; all access is guarded by an internal mutex.
15
+ */
16
+
17
+ #include "librats/core/bytes.h"
18
+
19
+ #include <cstdint>
20
+ #include <map>
21
+ #include <mutex>
22
+
23
+ namespace librats::bittorrent {
24
+
25
+ class StoreBuffer {
26
+ public:
27
+ /// Park a pending block. Replaces any existing entry at the same key.
28
+ void insert(std::uint32_t piece, std::uint32_t offset, const Bytes& data);
29
+
30
+ /// Drop a block once its write has landed on disk.
31
+ void erase(std::uint32_t piece, std::uint32_t offset);
32
+
33
+ /// Overlay any parked bytes for @p piece that intersect
34
+ /// [@p offset, @p offset + out.size()) onto @p out (indexed from @p offset).
35
+ void overlay(std::uint32_t piece, std::uint32_t offset, Bytes& out) const;
36
+
37
+ bool empty() const;
38
+ std::size_t size() const;
39
+
40
+ private:
41
+ using Key = std::pair<std::uint32_t, std::uint32_t>; // (piece, offset)
42
+
43
+ mutable std::mutex mutex_;
44
+ std::map<Key, Bytes> blocks_;
45
+ };
46
+
47
+ } // namespace librats::bittorrent