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,194 @@
1
+ #pragma once
2
+
3
+ /**
4
+ * @file peer_connection.h
5
+ * @brief One peer link: the BitTorrent wire handshake, message codec and the
6
+ * choke/interest state machine.
7
+ *
8
+ * A PeerConnection owns a non-blocking TCP socket registered with a Reactor and
9
+ * lives entirely on that reactor's thread. It turns the byte stream into
10
+ * protocol events delivered to an Observer, and offers send_* methods to emit
11
+ * messages. It deliberately knows nothing about pieces-to-request strategy or
12
+ * disk — the owning Torrent (a later phase) drives those through this surface.
13
+ *
14
+ * Wire format: a 68-byte handshake, then length-prefixed messages
15
+ * `[u32 length][u8 id][payload]` (length 0 = keep-alive). All integers are
16
+ * big-endian.
17
+ */
18
+
19
+ #include "librats/bittorrent/bitfield.h"
20
+ #include "librats/bittorrent/reactor.h"
21
+ #include "librats/bittorrent/types.h"
22
+ #include "librats/core/bytes.h"
23
+ #include "librats/core/chained_send_buffer.h"
24
+ #include "librats/core/receive_buffer.h"
25
+
26
+ #include <chrono>
27
+ #include <cstdint>
28
+ #include <functional>
29
+ #include <string>
30
+ #include <vector>
31
+
32
+ namespace librats::bittorrent {
33
+
34
+ enum class MessageId : std::uint8_t {
35
+ Choke = 0,
36
+ Unchoke = 1,
37
+ Interested = 2,
38
+ NotInterested = 3,
39
+ Have = 4,
40
+ Bitfield = 5,
41
+ Request = 6,
42
+ Piece = 7,
43
+ Cancel = 8,
44
+ Port = 9,
45
+ Extended = 20,
46
+ };
47
+
48
+ class PeerConnection {
49
+ public:
50
+ /// Protocol events. All fire on the reactor thread; ByteView arguments are
51
+ /// only valid for the duration of the call (copy if you need to keep them).
52
+ struct Observer {
53
+ virtual ~Observer() = default;
54
+ virtual void on_handshake(PeerConnection&, const InfoHash&, const PeerId&) {}
55
+ virtual void on_choke(PeerConnection&, bool peer_choking) {}
56
+ virtual void on_interest(PeerConnection&, bool peer_interested) {}
57
+ virtual void on_have(PeerConnection&, std::uint32_t piece) {}
58
+ virtual void on_bitfield(PeerConnection&, const Bitfield&) {}
59
+ virtual void on_request(PeerConnection&, std::uint32_t piece, std::uint32_t offset, std::uint32_t length) {}
60
+ virtual void on_piece(PeerConnection&, std::uint32_t piece, std::uint32_t offset, ByteView data) {}
61
+ virtual void on_cancel(PeerConnection&, std::uint32_t piece, std::uint32_t offset, std::uint32_t length) {}
62
+ virtual void on_port(PeerConnection&, std::uint16_t port) {}
63
+ virtual void on_extended(PeerConnection&, std::uint8_t ext_id, ByteView payload) {}
64
+ virtual void on_closed(PeerConnection&, const std::string& reason) {}
65
+ };
66
+
67
+ /// Late-binding info for an incoming connection: filled by the Resolver once
68
+ /// the peer's handshake reveals which torrent it is for.
69
+ struct Binding {
70
+ Observer* observer = nullptr;
71
+ std::uint32_t num_pieces = 0;
72
+ };
73
+ /// Maps an incoming handshake's info-hash to a torrent. Return false to reject.
74
+ using Resolver = std::function<bool(const InfoHash& their_info_hash, Binding& out)>;
75
+
76
+ /// Outgoing connection: we know the torrent up front.
77
+ /// @param num_pieces sizes the peer's bitfield; 0 if metadata isn't known yet.
78
+ PeerConnection(Reactor& reactor, socket_t sock, bool outgoing,
79
+ const InfoHash& info_hash, const PeerId& our_peer_id,
80
+ std::uint32_t num_pieces, Observer* observer,
81
+ std::string remote_ip = "", std::uint16_t remote_port = 0);
82
+ /// Incoming connection: the torrent is resolved from the peer's handshake.
83
+ PeerConnection(Reactor& reactor, socket_t sock, const PeerId& our_peer_id,
84
+ Resolver resolver, std::string remote_ip = "", std::uint16_t remote_port = 0);
85
+ ~PeerConnection();
86
+
87
+ PeerConnection(const PeerConnection&) = delete;
88
+ PeerConnection& operator=(const PeerConnection&) = delete;
89
+
90
+ /// Register with the reactor; an outgoing connection sends its handshake now.
91
+ void start();
92
+ /// Tear down: deregister, close the socket, fire on_closed once.
93
+ void close(const std::string& reason);
94
+
95
+ // ---- state ----
96
+ bool closed() const noexcept { return closed_; }
97
+ bool handshake_done() const noexcept { return handshake_sent_ && handshake_received_; }
98
+ bool outgoing() const noexcept { return outgoing_; }
99
+ bool am_choking() const noexcept { return am_choking_; }
100
+ bool am_interested() const noexcept { return am_interested_; }
101
+ bool peer_choking() const noexcept { return peer_choking_; }
102
+ bool peer_interested() const noexcept { return peer_interested_; }
103
+ const Bitfield& peer_bitfield() const noexcept { return peer_have_; }
104
+ const PeerId& peer_id() const noexcept { return peer_id_; }
105
+ const InfoHash& info_hash() const noexcept { return info_hash_; }
106
+ bool peer_supports_extensions() const noexcept { return reserved::has_extensions(peer_reserved_); }
107
+ const std::string& remote_ip() const noexcept { return remote_ip_; }
108
+ std::uint16_t remote_port() const noexcept { return remote_port_; }
109
+
110
+ // ---- send ----
111
+ void send_keepalive();
112
+ void send_choke();
113
+ void send_unchoke();
114
+ void send_interested();
115
+ void send_not_interested();
116
+ void send_have(std::uint32_t piece);
117
+ void send_bitfield(const Bitfield& bitfield);
118
+ void send_request(std::uint32_t piece, std::uint32_t offset, std::uint32_t length);
119
+ /// Takes ownership of `data` — the block goes into the send queue as its own
120
+ /// chunk, so a disk read is handed straight to the socket without a copy.
121
+ void send_piece(std::uint32_t piece, std::uint32_t offset, Bytes data);
122
+ void send_cancel(std::uint32_t piece, std::uint32_t offset, std::uint32_t length);
123
+ void send_port(std::uint16_t port);
124
+ void send_extended(std::uint8_t ext_id, ByteView payload);
125
+
126
+ private:
127
+ void on_io(std::uint32_t events);
128
+ void do_read();
129
+ std::size_t read_size() const; ///< bytes to offer the next recv() (see rx_need_)
130
+ void parse();
131
+ bool parse_handshake();
132
+ void send_handshake();
133
+ void dispatch(MessageId id, const std::uint8_t* payload, std::uint32_t len);
134
+
135
+ void send_message(MessageId id, const std::uint8_t* payload, std::uint32_t len);
136
+ /// Append to the send queue. No syscall: the caller flushes once the whole
137
+ /// message is queued, so a message never costs more than one send().
138
+ void queue(ByteView bytes) { if (!closed_) tx_.append(bytes); }
139
+ /// Queue a buffer the caller already owns — moved in, never copied.
140
+ void queue(Bytes bytes) { if (!closed_) tx_.append(std::move(bytes)); }
141
+ /// Push the queue to the socket with one gather-send, (dis)arm write interest,
142
+ /// and enforce the send high-water mark. May close the connection.
143
+ void flush();
144
+ void want_write(bool on);
145
+ /// Periodic self-rescheduling tick: enforces the handshake/idle deadlines and
146
+ /// emits keep-alives. Stops rescheduling once the connection is closed.
147
+ void tick();
148
+
149
+ Reactor& reactor_;
150
+ socket_t sock_;
151
+ bool outgoing_;
152
+ InfoHash info_hash_;
153
+ PeerId our_peer_id_;
154
+ PeerId peer_id_{};
155
+ std::uint32_t num_pieces_;
156
+ Observer* obs_;
157
+ Resolver resolver_; ///< incoming only; resolves the torrent
158
+ bool bound_ = true; ///< false for an unresolved incoming connection
159
+ std::string remote_ip_; ///< peer's address (source for incoming, dialed for outgoing)
160
+ std::uint16_t remote_port_ = 0;
161
+
162
+ ReceiveBuffer rx_;
163
+ /// Wire size of the message rx_ is mid-way through (4-byte prefix included), once
164
+ /// that prefix has been read; 0 when no message is in flight. Lets the next recv()
165
+ /// size rx_ for the whole message in one go. Peer-declared, hence capped.
166
+ std::size_t rx_need_ = 0;
167
+ ChainedSendBuffer tx_;
168
+ bool want_write_ = false;
169
+
170
+ // Timeout bookkeeping, all evaluated by the periodic tick().
171
+ TimerId tick_timer_ = kInvalidTimerId;
172
+ std::chrono::steady_clock::time_point created_{}; ///< start() time — handshake deadline
173
+ std::chrono::steady_clock::time_point last_recv_{}; ///< last byte received — idle deadline
174
+ std::chrono::steady_clock::time_point last_sent_{}; ///< last byte sent — keep-alive timer
175
+
176
+ bool started_ = false;
177
+ bool handshake_sent_ = false;
178
+ bool handshake_received_= false;
179
+ bool closed_ = false;
180
+
181
+ bool am_choking_ = true;
182
+ bool am_interested_ = false;
183
+ bool peer_choking_ = true;
184
+ bool peer_interested_ = false;
185
+ /// A bitfield is only valid as the peer's first piece-state message (BEP 3).
186
+ /// Set once the peer has sent a bitfield or any HAVE; a later bitfield is then
187
+ /// rejected so we can't double-count its availability against a single per-bit
188
+ /// decrement at disconnect.
189
+ bool piece_state_begun_ = false;
190
+ Bitfield peer_have_;
191
+ ReservedBytes peer_reserved_{};
192
+ };
193
+
194
+ } // namespace librats::bittorrent
@@ -0,0 +1,68 @@
1
+ #include "librats/bittorrent/peer_list.h"
2
+
3
+ #include <algorithm>
4
+
5
+ namespace librats::bittorrent {
6
+
7
+ bool PeerList::add(const std::string& ip, std::uint16_t port, PeerSource source) {
8
+ if (ip.empty() || port == 0) return false;
9
+ auto [it, inserted] = peers_.try_emplace(key(ip, port));
10
+ Peer& p = it->second;
11
+ p.sources |= std::uint8_t(source);
12
+ if (inserted) { p.ip = ip; p.port = port; }
13
+ return inserted;
14
+ }
15
+
16
+ std::vector<PeerList::Endpoint> PeerList::connect_candidates(std::size_t max) {
17
+ std::vector<Peer*> eligible_peers;
18
+ for (auto& [k, p] : peers_)
19
+ if (eligible(p)) eligible_peers.push_back(&p);
20
+
21
+ // Fewest past failures first; ties broken by richer source provenance so a
22
+ // tracker/DHT-vouched peer outranks one only seen via PEX.
23
+ std::sort(eligible_peers.begin(), eligible_peers.end(), [](const Peer* a, const Peer* b) {
24
+ if (a->fail_count != b->fail_count) return a->fail_count < b->fail_count;
25
+ return a->sources > b->sources;
26
+ });
27
+
28
+ std::vector<Endpoint> out;
29
+ const std::size_t take = (std::min)(max, eligible_peers.size());
30
+ out.reserve(take);
31
+ for (std::size_t i = 0; i < take; ++i) {
32
+ eligible_peers[i]->connecting = true;
33
+ out.push_back(Endpoint{eligible_peers[i]->ip, eligible_peers[i]->port});
34
+ }
35
+ return out;
36
+ }
37
+
38
+ void PeerList::set_connected(const std::string& ip, std::uint16_t port, bool connected) {
39
+ auto it = peers_.find(key(ip, port));
40
+ if (it == peers_.end()) return;
41
+ it->second.connected = connected;
42
+ it->second.connecting = false;
43
+ if (connected) it->second.fail_count = 0; // a successful connect clears the penalty
44
+ }
45
+
46
+ void PeerList::on_connect_failed(const std::string& ip, std::uint16_t port) {
47
+ auto it = peers_.find(key(ip, port));
48
+ if (it == peers_.end()) return;
49
+ it->second.connecting = false;
50
+ ++it->second.fail_count;
51
+ }
52
+
53
+ void PeerList::ban(const std::string& ip, std::uint16_t port) {
54
+ auto it = peers_.find(key(ip, port));
55
+ if (it != peers_.end()) it->second.banned = true;
56
+ }
57
+
58
+ std::size_t PeerList::num_candidates() const {
59
+ std::size_t n = 0;
60
+ for (const auto& [k, p] : peers_) if (eligible(p)) ++n;
61
+ return n;
62
+ }
63
+
64
+ bool PeerList::contains(const std::string& ip, std::uint16_t port) const {
65
+ return peers_.count(key(ip, port)) != 0;
66
+ }
67
+
68
+ } // namespace librats::bittorrent
@@ -0,0 +1,75 @@
1
+ #pragma once
2
+
3
+ /**
4
+ * @file peer_list.h
5
+ * @brief The set of *known* peer addresses for a torrent (distinct from the live
6
+ * connections).
7
+ *
8
+ * Every discovery source — tracker, DHT, PEX, LSD, incoming — funnels addresses
9
+ * here; the Torrent then asks for connect_candidates() to dial. The list
10
+ * deduplicates, remembers which sources vouched for a peer, counts connection
11
+ * failures (so hopeless peers drift to the back and eventually drop out), and
12
+ * supports banning. Owned by one torrent on the reactor thread — not thread-safe.
13
+ */
14
+
15
+ #include <cstddef>
16
+ #include <cstdint>
17
+ #include <string>
18
+ #include <unordered_map>
19
+ #include <utility>
20
+ #include <vector>
21
+
22
+ namespace librats::bittorrent {
23
+
24
+ enum class PeerSource : std::uint8_t {
25
+ Tracker = 1,
26
+ Dht = 2,
27
+ Pex = 4,
28
+ Lsd = 8,
29
+ Incoming = 16,
30
+ };
31
+
32
+ class PeerList {
33
+ public:
34
+ struct Endpoint { std::string ip; std::uint16_t port; };
35
+
36
+ struct Peer {
37
+ std::string ip;
38
+ std::uint16_t port = 0;
39
+ std::uint8_t sources = 0;
40
+ bool connected = false;
41
+ bool connecting = false;
42
+ bool banned = false;
43
+ std::uint32_t fail_count = 0;
44
+ };
45
+
46
+ static constexpr std::uint32_t kMaxFails = 5;
47
+
48
+ /// Add or merge a candidate. Returns true if it was newly created.
49
+ bool add(const std::string& ip, std::uint16_t port, PeerSource source);
50
+
51
+ /// Up to @p max eligible peers to dial (not connected/connecting/banned, and
52
+ /// under the failure limit), best first. The returned peers are marked
53
+ /// `connecting` so they aren't handed out again until resolved.
54
+ std::vector<Endpoint> connect_candidates(std::size_t max);
55
+
56
+ void set_connected(const std::string& ip, std::uint16_t port, bool connected);
57
+ void on_connect_failed(const std::string& ip, std::uint16_t port);
58
+ void ban(const std::string& ip, std::uint16_t port);
59
+
60
+ std::size_t size() const noexcept { return peers_.size(); }
61
+ std::size_t num_candidates() const; ///< count currently eligible to dial
62
+ bool contains(const std::string& ip, std::uint16_t port) const;
63
+
64
+ private:
65
+ static std::string key(const std::string& ip, std::uint16_t port) {
66
+ return ip + ":" + std::to_string(port);
67
+ }
68
+ bool eligible(const Peer& p) const noexcept {
69
+ return !p.connected && !p.connecting && !p.banned && p.fail_count < kMaxFails;
70
+ }
71
+
72
+ std::unordered_map<std::string, Peer> peers_;
73
+ };
74
+
75
+ } // namespace librats::bittorrent