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,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