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,77 @@
1
+ #include "librats/bittorrent/file_storage.h"
2
+ #include "librats/bittorrent/types.h" // kBlockSize
3
+
4
+ #include <algorithm>
5
+ #include <limits>
6
+
7
+ namespace librats::bittorrent {
8
+
9
+ bool FileStorage::add_file(std::string path, std::int64_t size) {
10
+ // Reject a negative size or a running total that would overflow int64: a
11
+ // hostile .torrent could otherwise trigger signed-overflow UB here and a
12
+ // garbage num_pieces() downstream. Leave the layout untouched so the caller
13
+ // can bail cleanly.
14
+ if (size < 0 || size > std::numeric_limits<std::int64_t>::max() - total_size_)
15
+ return false;
16
+ files_.push_back(FileEntry{std::move(path), size, total_size_});
17
+ total_size_ += size;
18
+ return true;
19
+ }
20
+
21
+ void FileStorage::clear() {
22
+ files_.clear();
23
+ name_.clear();
24
+ piece_length_ = 0;
25
+ total_size_ = 0;
26
+ }
27
+
28
+ std::uint32_t FileStorage::num_pieces() const noexcept {
29
+ if (piece_length_ == 0) return 0;
30
+ return std::uint32_t((total_size_ + piece_length_ - 1) / piece_length_);
31
+ }
32
+
33
+ std::uint32_t FileStorage::piece_size(std::uint32_t piece) const noexcept {
34
+ const std::uint32_t n = num_pieces();
35
+ if (piece + 1 < n) return piece_length_;
36
+ // Final piece: the remainder. (Also the only piece for tiny torrents.)
37
+ const std::int64_t tail = total_size_ - std::int64_t(piece) * piece_length_;
38
+ if (tail <= 0) return 0;
39
+ return std::uint32_t(std::min<std::int64_t>(tail, piece_length_));
40
+ }
41
+
42
+ std::uint32_t FileStorage::blocks_in_piece(std::uint32_t piece) const noexcept {
43
+ const std::uint32_t ps = piece_size(piece);
44
+ return (ps + kBlockSize - 1) / kBlockSize;
45
+ }
46
+
47
+ std::vector<FileSlice> FileStorage::map_block(std::uint32_t piece, std::uint32_t offset,
48
+ std::int64_t size) const {
49
+ std::vector<FileSlice> slices;
50
+ if (size <= 0 || files_.empty()) return slices;
51
+
52
+ std::int64_t abs = std::int64_t(piece) * piece_length_ + offset;
53
+ if (abs >= total_size_) return slices;
54
+ std::int64_t remaining = (std::min)(size, total_size_ - abs); // clamp to payload
55
+
56
+ // Binary search: the file containing `abs` is the last one whose offset <= abs.
57
+ // (Zero-length files share an offset with the following file; picking the last
58
+ // such index lands on the real, non-empty file, and the loop skips empties.)
59
+ std::size_t f = std::size_t(
60
+ std::upper_bound(files_.begin(), files_.end(), abs,
61
+ [](std::int64_t a, const FileEntry& e) { return a < e.offset; })
62
+ - files_.begin());
63
+ if (f > 0) --f;
64
+
65
+ while (remaining > 0 && f < files_.size()) {
66
+ const std::int64_t file_off = abs - files_[f].offset;
67
+ if (file_off >= files_[f].size) { ++f; continue; } // empty / already past this file
68
+ const std::int64_t take = (std::min)(remaining, files_[f].size - file_off);
69
+ slices.push_back(FileSlice{f, file_off, take});
70
+ remaining -= take;
71
+ abs += take;
72
+ ++f;
73
+ }
74
+ return slices;
75
+ }
76
+
77
+ } // namespace librats::bittorrent
@@ -0,0 +1,79 @@
1
+ #pragma once
2
+
3
+ /**
4
+ * @file file_storage.h
5
+ * @brief The file layout of a torrent and the piece <-> file mapping.
6
+ *
7
+ * A torrent's payload is one contiguous byte space: files are laid end-to-end
8
+ * in order, each at a running @c offset. Pieces are fixed-size windows over that
9
+ * space (the final piece is short). FileStorage answers the two questions the
10
+ * disk and wire layers need: "how big is piece i?" and "which file regions does
11
+ * a (piece, offset, length) range touch?". The latter (map_block) is O(log n)
12
+ * via a binary search over the sorted file offsets.
13
+ */
14
+
15
+ #include "librats/util/rats_export.h"
16
+
17
+ #include <cstddef>
18
+ #include <cstdint>
19
+ #include <string>
20
+ #include <vector>
21
+
22
+ namespace librats::bittorrent {
23
+
24
+ /// One file in the torrent. @c path is the full relative path including the
25
+ /// torrent name as its first component (so the disk layer just joins it onto
26
+ /// the save path). @c offset is the file's start in the torrent byte space.
27
+ struct FileEntry {
28
+ std::string path;
29
+ std::int64_t size = 0;
30
+ std::int64_t offset = 0;
31
+ };
32
+
33
+ /// A contiguous region of a single file — one fragment of a mapped block.
34
+ struct FileSlice {
35
+ std::size_t file_index = 0;
36
+ std::int64_t offset = 0; ///< byte offset within the file
37
+ std::int64_t size = 0;
38
+ };
39
+
40
+ class RATS_API FileStorage {
41
+ public:
42
+ void set_piece_length(std::uint32_t length) noexcept { piece_length_ = length; }
43
+ void set_name(std::string name) { name_ = std::move(name); }
44
+ /// Append a file (its offset is computed from the running total). Returns
45
+ /// false and leaves the layout unchanged if @p size is negative or would
46
+ /// overflow the int64 running total — a hostile .torrent must be rejected
47
+ /// rather than driving signed-overflow UB and a garbage num_pieces().
48
+ bool add_file(std::string path, std::int64_t size);
49
+ void clear();
50
+
51
+ const std::string& name() const noexcept { return name_; }
52
+ std::uint32_t piece_length() const noexcept { return piece_length_; }
53
+ std::int64_t total_size() const noexcept { return total_size_; }
54
+ std::size_t num_files() const noexcept { return files_.size(); }
55
+ const FileEntry& file_at(std::size_t i) const { return files_[i]; }
56
+ const std::vector<FileEntry>& files() const noexcept { return files_; }
57
+
58
+ /// A layout is usable once it has a piece length and at least one file.
59
+ bool is_valid() const noexcept { return piece_length_ > 0 && !files_.empty(); }
60
+
61
+ std::uint32_t num_pieces() const noexcept;
62
+ /// Size of piece @p piece — piece_length except a possibly-short final piece.
63
+ std::uint32_t piece_size(std::uint32_t piece) const noexcept;
64
+ /// Number of 16 KiB blocks in piece @p piece (the last block may be short).
65
+ std::uint32_t blocks_in_piece(std::uint32_t piece) const noexcept;
66
+
67
+ /// Map a byte range within a piece to the file regions it covers. The range
68
+ /// is clamped to the torrent's total size; zero-length files are skipped.
69
+ std::vector<FileSlice> map_block(std::uint32_t piece, std::uint32_t offset,
70
+ std::int64_t size) const;
71
+
72
+ private:
73
+ std::vector<FileEntry> files_;
74
+ std::string name_;
75
+ std::uint32_t piece_length_ = 0;
76
+ std::int64_t total_size_ = 0;
77
+ };
78
+
79
+ } // namespace librats::bittorrent
@@ -0,0 +1,42 @@
1
+ #pragma once
2
+
3
+ /**
4
+ * @file log.h
5
+ * @brief Small logging helpers shared across the BitTorrent modules.
6
+ *
7
+ * Formatting sugar on top of util/logger.h — nothing more. BitTorrent logs under a
8
+ * set of dot-namespaced tags so each component gets its own stable colour and is
9
+ * easy to grep (mirrors the dht.* scheme):
10
+ *
11
+ * "bt.client" — the session: listener, accept/dial, add/remove torrent
12
+ * "bt.torrent" — one torrent's lifecycle: state transitions, pieces, choking
13
+ * "bt.peer" — a peer link: handshake and disconnect (with reason)
14
+ * "bt.tracker" — per-tracker HTTP/UDP announce results
15
+ * "bt.meta" — magnet metadata fetch (BEP 9)
16
+ * "bt.disk" — disk I/O failures
17
+ * "bt.picker" — piece selection (end-game entry)
18
+ * "bt.node" — the Node subsystem wrapper
19
+ *
20
+ * Conventions: an info-hash renders via short_hash() (8 leading hex, like a git
21
+ * short hash); a peer renders as "ip:port". Direction/outcome use glyphs —
22
+ * → outgoing, ← incoming, ✓ success, ✗ failure — matching the DHT logs.
23
+ */
24
+
25
+ #include "librats/bittorrent/types.h"
26
+ #include "librats/util/logger.h"
27
+
28
+ #include <cstddef>
29
+ #include <string>
30
+
31
+ namespace librats::bittorrent {
32
+
33
+ /// Compact, log-friendly rendering of a 20-byte info-hash: its leading `chars`
34
+ /// hex digits (default 8, like a git short hash). The full 40-char id is
35
+ /// unreadable in a log line and its prefix is more than enough to follow one
36
+ /// torrent across lines. Use to_hex(id) only where the complete id matters.
37
+ inline std::string short_hash(const InfoHash& id, std::size_t chars = 8) {
38
+ const std::string full = to_hex(id);
39
+ return chars >= full.size() ? full : full.substr(0, chars);
40
+ }
41
+
42
+ } // namespace librats::bittorrent
@@ -0,0 +1,98 @@
1
+ #include "librats/bittorrent/magnet_uri.h"
2
+
3
+ #include <algorithm>
4
+ #include <cctype>
5
+
6
+ namespace librats::bittorrent {
7
+
8
+ namespace {
9
+
10
+ /// Percent-decode a URL component (leaves '+' as a literal, as magnet links do).
11
+ std::string url_decode(const std::string& s) {
12
+ std::string out;
13
+ out.reserve(s.size());
14
+ for (std::size_t i = 0; i < s.size(); ++i) {
15
+ if (s[i] == '%' && i + 2 < s.size()) {
16
+ auto hex = [](char c) -> int {
17
+ if (c >= '0' && c <= '9') return c - '0';
18
+ if (c >= 'a' && c <= 'f') return c - 'a' + 10;
19
+ if (c >= 'A' && c <= 'F') return c - 'A' + 10;
20
+ return -1;
21
+ };
22
+ const int hi = hex(s[i + 1]), lo = hex(s[i + 2]);
23
+ if (hi >= 0 && lo >= 0) { out.push_back(char(hi << 4 | lo)); i += 2; continue; }
24
+ }
25
+ out.push_back(s[i]);
26
+ }
27
+ return out;
28
+ }
29
+
30
+ /// Decode a 32-character RFC 4648 base32 string into a 20-byte info-hash.
31
+ std::optional<InfoHash> base32_to_info_hash(const std::string& in) {
32
+ if (in.size() != 32) return std::nullopt;
33
+ auto value = [](char c) -> int {
34
+ c = char(std::toupper(static_cast<unsigned char>(c)));
35
+ if (c >= 'A' && c <= 'Z') return c - 'A';
36
+ if (c >= '2' && c <= '7') return c - '2' + 26;
37
+ return -1;
38
+ };
39
+ InfoHash out{};
40
+ std::uint32_t bits = 0;
41
+ int bit_count = 0;
42
+ std::size_t byte = 0;
43
+ for (char c : in) {
44
+ const int v = value(c);
45
+ if (v < 0) return std::nullopt;
46
+ bits = bits << 5 | std::uint32_t(v);
47
+ bit_count += 5;
48
+ if (bit_count >= 8) {
49
+ bit_count -= 8;
50
+ out[byte++] = std::uint8_t(bits >> bit_count);
51
+ }
52
+ }
53
+ return out; // 32 * 5 = 160 bits = exactly 20 bytes
54
+ }
55
+
56
+ } // namespace
57
+
58
+ std::optional<MagnetUri> MagnetUri::parse(const std::string& uri) {
59
+ constexpr char kPrefix[] = "magnet:?";
60
+ if (uri.rfind(kPrefix, 0) != 0) return std::nullopt;
61
+
62
+ MagnetUri result;
63
+ const std::string query = uri.substr(sizeof(kPrefix) - 1);
64
+
65
+ std::size_t pos = 0;
66
+ while (pos < query.size()) {
67
+ std::size_t amp = query.find('&', pos);
68
+ if (amp == std::string::npos) amp = query.size();
69
+ const std::string token = query.substr(pos, amp - pos);
70
+ pos = amp + 1;
71
+
72
+ const std::size_t eq = token.find('=');
73
+ if (eq == std::string::npos) continue;
74
+ const std::string key = token.substr(0, eq);
75
+ const std::string val = url_decode(token.substr(eq + 1));
76
+
77
+ if (key == "xt") {
78
+ constexpr char kBtih[] = "urn:btih:";
79
+ if (val.rfind(kBtih, 0) == 0) {
80
+ const std::string id = val.substr(sizeof(kBtih) - 1);
81
+ if (auto h = info_hash_from_hex(id)) result.info_hash = *h;
82
+ else if (auto b = base32_to_info_hash(id)) result.info_hash = *b;
83
+ }
84
+ // urn:btmh: (v2) intentionally ignored for now.
85
+ } else if (key == "dn") {
86
+ result.display_name = val;
87
+ } else if (key == "tr") {
88
+ if (!val.empty()) result.trackers.push_back(val);
89
+ } else if (key == "ws") {
90
+ if (!val.empty()) result.web_seeds.push_back(val);
91
+ }
92
+ }
93
+
94
+ if (!result.is_valid()) return std::nullopt;
95
+ return result;
96
+ }
97
+
98
+ } // namespace librats::bittorrent
@@ -0,0 +1,35 @@
1
+ #pragma once
2
+
3
+ /**
4
+ * @file magnet_uri.h
5
+ * @brief Parsing of magnet links (BEP 9 / BEP 53 subset).
6
+ *
7
+ * A magnet link carries an info-hash (and optionally a name, trackers and web
8
+ * seeds) but no metadata — the file list and piece hashes must still be fetched
9
+ * from peers via ut_metadata. We accept the v1 `xt=urn:btih:` form with either a
10
+ * 40-char hex or a 32-char base32 SHA-1.
11
+ */
12
+
13
+ #include "librats/util/rats_export.h"
14
+ #include "librats/bittorrent/types.h"
15
+
16
+ #include <optional>
17
+ #include <string>
18
+ #include <vector>
19
+
20
+ namespace librats::bittorrent {
21
+
22
+ struct RATS_API MagnetUri {
23
+ InfoHash info_hash{};
24
+ std::string display_name; ///< dn
25
+ std::vector<std::string> trackers; ///< tr
26
+ std::vector<std::string> web_seeds; ///< ws
27
+
28
+ bool is_valid() const noexcept { return !is_all_zero(info_hash); }
29
+
30
+ /// Parse a "magnet:?…" URI. nullopt if it is not a magnet link or carries no
31
+ /// valid v1 info-hash.
32
+ static std::optional<MagnetUri> parse(const std::string& uri);
33
+ };
34
+
35
+ } // namespace librats::bittorrent