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
@@ -1,410 +0,0 @@
1
- #include "bt_resume_data.h"
2
- #include "fs.h"
3
- #include "logger.h"
4
-
5
- #include <fstream>
6
- #include <sstream>
7
-
8
- namespace librats {
9
-
10
- //=============================================================================
11
- // Constants
12
- //=============================================================================
13
-
14
- static constexpr const char* RESUME_FILE_FORMAT = "librats resume file";
15
- static constexpr int RESUME_FILE_VERSION = 1;
16
-
17
- //=============================================================================
18
- // Write Resume Data
19
- //=============================================================================
20
-
21
- std::vector<uint8_t> write_resume_data(const TorrentResumeData& data) {
22
- BencodeValue dict = BencodeValue::create_dict();
23
-
24
- // File format identification
25
- dict["file-format"] = BencodeValue(std::string(RESUME_FILE_FORMAT));
26
- dict["file-version"] = BencodeValue(static_cast<int64_t>(RESUME_FILE_VERSION));
27
- dict["librats-version"] = BencodeValue(std::string("1.0.0"));
28
-
29
- // Info hash (as raw 20-byte string)
30
- std::string hash_str(reinterpret_cast<const char*>(data.info_hash.data()),
31
- data.info_hash.size());
32
- dict["info-hash"] = BencodeValue(hash_str);
33
-
34
- // Name and save path
35
- if (!data.name.empty()) {
36
- dict["name"] = BencodeValue(data.name);
37
- }
38
- dict["save_path"] = BencodeValue(data.save_path);
39
-
40
- // Have pieces bitfield
41
- // Store as a string where each byte represents one piece:
42
- // 0 = don't have, 1 = have (verified)
43
- if (data.have_pieces.size() > 0) {
44
- std::string pieces_str;
45
- pieces_str.resize(data.have_pieces.size());
46
- for (size_t i = 0; i < data.have_pieces.size(); ++i) {
47
- pieces_str[i] = data.have_pieces.get_bit(static_cast<uint32_t>(i)) ? 1 : 0;
48
- }
49
- dict["pieces"] = BencodeValue(pieces_str);
50
- }
51
-
52
- // Unfinished pieces (partial downloads)
53
- if (!data.unfinished_pieces.empty()) {
54
- BencodeValue unfinished_list = BencodeValue::create_list();
55
-
56
- for (const auto& [piece_idx, blocks] : data.unfinished_pieces) {
57
- BencodeValue piece_dict = BencodeValue::create_dict();
58
- piece_dict["piece"] = BencodeValue(static_cast<int64_t>(piece_idx));
59
-
60
- // Pack blocks bitfield into bytes
61
- // Each bit represents a 16KB block
62
- size_t num_bytes = (blocks.size() + 7) / 8;
63
- std::string bitmask;
64
- bitmask.resize(num_bytes, 0);
65
-
66
- for (size_t i = 0; i < blocks.size(); ++i) {
67
- if (blocks.get_bit(static_cast<uint32_t>(i))) {
68
- bitmask[i / 8] |= static_cast<char>(0x80 >> (i % 8));
69
- }
70
- }
71
-
72
- piece_dict["bitmask"] = BencodeValue(bitmask);
73
- piece_dict["num_blocks"] = BencodeValue(static_cast<int64_t>(blocks.size()));
74
-
75
- unfinished_list.push_back(piece_dict);
76
- }
77
-
78
- dict["unfinished"] = unfinished_list;
79
- }
80
-
81
- // Statistics
82
- dict["total_uploaded"] = BencodeValue(static_cast<int64_t>(data.total_uploaded));
83
- dict["total_downloaded"] = BencodeValue(static_cast<int64_t>(data.total_downloaded));
84
- dict["active_time"] = BencodeValue(data.active_time);
85
- dict["seeding_time"] = BencodeValue(data.seeding_time);
86
- dict["added_time"] = BencodeValue(data.added_time);
87
- dict["completed_time"] = BencodeValue(data.completed_time);
88
-
89
- // Configuration
90
- dict["sequential_download"] = BencodeValue(data.sequential_download ? int64_t(1) : int64_t(0));
91
- if (data.max_connections >= 0) {
92
- dict["max_connections"] = BencodeValue(static_cast<int64_t>(data.max_connections));
93
- }
94
- if (data.max_uploads >= 0) {
95
- dict["max_uploads"] = BencodeValue(static_cast<int64_t>(data.max_uploads));
96
- }
97
- if (data.download_limit >= 0) {
98
- dict["download_rate_limit"] = BencodeValue(data.download_limit);
99
- }
100
- if (data.upload_limit >= 0) {
101
- dict["upload_rate_limit"] = BencodeValue(data.upload_limit);
102
- }
103
-
104
- // Optional: info dict (for magnet links that downloaded metadata)
105
- if (!data.info_dict.empty()) {
106
- std::string info_str(reinterpret_cast<const char*>(data.info_dict.data()),
107
- data.info_dict.size());
108
- dict["info"] = BencodeValue(info_str);
109
- }
110
-
111
- // Optional: peers cache
112
- if (!data.peers.empty()) {
113
- // IPv4 peers: 6 bytes each (4 byte IP + 2 byte port)
114
- std::string peers_str;
115
- for (const auto& [ip, port] : data.peers) {
116
- // Parse IP address to 4 bytes
117
- uint32_t ip_num = 0;
118
- int a, b, c, d;
119
- if (sscanf(ip.c_str(), "%d.%d.%d.%d", &a, &b, &c, &d) == 4) {
120
- ip_num = (static_cast<uint32_t>(a) << 24) |
121
- (static_cast<uint32_t>(b) << 16) |
122
- (static_cast<uint32_t>(c) << 8) |
123
- static_cast<uint32_t>(d);
124
-
125
- peers_str.push_back(static_cast<char>((ip_num >> 24) & 0xFF));
126
- peers_str.push_back(static_cast<char>((ip_num >> 16) & 0xFF));
127
- peers_str.push_back(static_cast<char>((ip_num >> 8) & 0xFF));
128
- peers_str.push_back(static_cast<char>(ip_num & 0xFF));
129
- peers_str.push_back(static_cast<char>((port >> 8) & 0xFF));
130
- peers_str.push_back(static_cast<char>(port & 0xFF));
131
- }
132
- }
133
- if (!peers_str.empty()) {
134
- dict["peers"] = BencodeValue(peers_str);
135
- }
136
- }
137
-
138
- return dict.encode();
139
- }
140
-
141
- bool write_resume_data_file(const TorrentResumeData& data, const std::string& path) {
142
- auto encoded = write_resume_data(data);
143
- if (encoded.empty()) {
144
- LOG_ERROR("ResumeData", "Failed to encode resume data");
145
- return false;
146
- }
147
-
148
- // Create parent directory if needed
149
- std::string parent = get_parent_directory(path);
150
- if (!parent.empty() && !directory_exists(parent.c_str())) {
151
- LOG_DEBUG("ResumeData", "Creating resume directory: " + parent);
152
- if (!create_directories(parent.c_str())) {
153
- LOG_ERROR("ResumeData", "Failed to create resume directory: " + parent);
154
- return false;
155
- }
156
- }
157
-
158
- std::ofstream file(path, std::ios::binary);
159
- if (!file) {
160
- LOG_ERROR("ResumeData", "Failed to open resume file for writing: " + path);
161
- return false;
162
- }
163
-
164
- file.write(reinterpret_cast<const char*>(encoded.data()),
165
- static_cast<std::streamsize>(encoded.size()));
166
-
167
- if (!file) {
168
- LOG_ERROR("ResumeData", "Failed to write resume file: " + path);
169
- return false;
170
- }
171
-
172
- LOG_DEBUG("ResumeData", "Saved resume data to " + path +
173
- " (" + std::to_string(encoded.size()) + " bytes)");
174
-
175
- return true;
176
- }
177
-
178
- //=============================================================================
179
- // Read Resume Data
180
- //=============================================================================
181
-
182
- std::optional<TorrentResumeData> read_resume_data(
183
- const std::vector<uint8_t>& buffer,
184
- std::string* error_out) {
185
-
186
- BencodeValue decoded;
187
- try {
188
- decoded = BencodeDecoder::decode(buffer);
189
- } catch (const std::exception& e) {
190
- if (error_out) *error_out = std::string("Failed to decode bencode: ") + e.what();
191
- return std::nullopt;
192
- }
193
-
194
- if (!decoded.is_dict()) {
195
- if (error_out) *error_out = "Resume data is not a dictionary";
196
- return std::nullopt;
197
- }
198
-
199
- const auto& dict = decoded.as_dict();
200
-
201
- // Verify file format
202
- auto format_it = dict.find("file-format");
203
- if (format_it == dict.end() || !format_it->second.is_string()) {
204
- if (error_out) *error_out = "Missing or invalid file-format";
205
- return std::nullopt;
206
- }
207
-
208
- if (format_it->second.as_string() != RESUME_FILE_FORMAT) {
209
- if (error_out) *error_out = "Unknown resume file format: " + format_it->second.as_string();
210
- return std::nullopt;
211
- }
212
-
213
- // Check version
214
- auto version_it = dict.find("file-version");
215
- if (version_it != dict.end() && version_it->second.is_integer()) {
216
- int version = static_cast<int>(version_it->second.as_integer());
217
- if (version > RESUME_FILE_VERSION) {
218
- if (error_out) *error_out = "Resume file version too new: " + std::to_string(version);
219
- return std::nullopt;
220
- }
221
- }
222
-
223
- TorrentResumeData data;
224
-
225
- // Info hash (required)
226
- auto hash_it = dict.find("info-hash");
227
- if (hash_it == dict.end() || !hash_it->second.is_string()) {
228
- if (error_out) *error_out = "Missing info-hash";
229
- return std::nullopt;
230
- }
231
-
232
- const auto& hash_str = hash_it->second.as_string();
233
- if (hash_str.size() != 20) {
234
- if (error_out) *error_out = "Invalid info-hash size";
235
- return std::nullopt;
236
- }
237
- std::copy(hash_str.begin(), hash_str.end(), data.info_hash.begin());
238
-
239
- // Name
240
- auto name_it = dict.find("name");
241
- if (name_it != dict.end() && name_it->second.is_string()) {
242
- data.name = name_it->second.as_string();
243
- }
244
-
245
- // Save path
246
- auto path_it = dict.find("save_path");
247
- if (path_it != dict.end() && path_it->second.is_string()) {
248
- data.save_path = path_it->second.as_string();
249
- }
250
-
251
- // Have pieces
252
- auto pieces_it = dict.find("pieces");
253
- if (pieces_it != dict.end() && pieces_it->second.is_string()) {
254
- const auto& pieces_str = pieces_it->second.as_string();
255
- data.have_pieces = Bitfield(static_cast<uint32_t>(pieces_str.size()));
256
-
257
- for (size_t i = 0; i < pieces_str.size(); ++i) {
258
- if (pieces_str[i] & 1) {
259
- data.have_pieces.set_bit(static_cast<uint32_t>(i));
260
- }
261
- }
262
- }
263
-
264
- // Unfinished pieces
265
- auto unfinished_it = dict.find("unfinished");
266
- if (unfinished_it != dict.end() && unfinished_it->second.is_list()) {
267
- const auto& unfinished_list = unfinished_it->second.as_list();
268
-
269
- for (const auto& entry : unfinished_list) {
270
- if (!entry.is_dict()) continue;
271
-
272
- const auto& piece_dict = entry.as_dict();
273
-
274
- auto piece_it = piece_dict.find("piece");
275
- if (piece_it == piece_dict.end() || !piece_it->second.is_integer()) {
276
- continue;
277
- }
278
- uint32_t piece_idx = static_cast<uint32_t>(piece_it->second.as_integer());
279
-
280
- auto bitmask_it = piece_dict.find("bitmask");
281
- if (bitmask_it == piece_dict.end() || !bitmask_it->second.is_string()) {
282
- continue;
283
- }
284
- const auto& bitmask = bitmask_it->second.as_string();
285
-
286
- // Get number of blocks (optional, for accurate size)
287
- size_t num_blocks = bitmask.size() * 8;
288
- auto num_blocks_it = piece_dict.find("num_blocks");
289
- if (num_blocks_it != piece_dict.end() && num_blocks_it->second.is_integer()) {
290
- num_blocks = static_cast<size_t>(num_blocks_it->second.as_integer());
291
- }
292
-
293
- Bitfield blocks(static_cast<uint32_t>(num_blocks));
294
- for (size_t i = 0; i < num_blocks; ++i) {
295
- if (i / 8 < bitmask.size()) {
296
- if (bitmask[i / 8] & (0x80 >> (i % 8))) {
297
- blocks.set_bit(static_cast<uint32_t>(i));
298
- }
299
- }
300
- }
301
-
302
- data.unfinished_pieces[piece_idx] = blocks;
303
- }
304
- }
305
-
306
- // Statistics
307
- auto read_int = [&dict](const char* key, int64_t default_val = 0) -> int64_t {
308
- auto it = dict.find(key);
309
- if (it != dict.end() && it->second.is_integer()) {
310
- return it->second.as_integer();
311
- }
312
- return default_val;
313
- };
314
-
315
- data.total_uploaded = static_cast<uint64_t>(read_int("total_uploaded"));
316
- data.total_downloaded = static_cast<uint64_t>(read_int("total_downloaded"));
317
- data.active_time = read_int("active_time");
318
- data.seeding_time = read_int("seeding_time");
319
- data.added_time = read_int("added_time");
320
- data.completed_time = read_int("completed_time");
321
-
322
- // Configuration
323
- data.sequential_download = read_int("sequential_download") != 0;
324
- data.max_connections = static_cast<int>(read_int("max_connections", -1));
325
- data.max_uploads = static_cast<int>(read_int("max_uploads", -1));
326
- data.download_limit = read_int("download_rate_limit", -1);
327
- data.upload_limit = read_int("upload_rate_limit", -1);
328
-
329
- // Optional: info dict
330
- auto info_it = dict.find("info");
331
- if (info_it != dict.end() && info_it->second.is_string()) {
332
- const auto& info_str = info_it->second.as_string();
333
- data.info_dict.assign(info_str.begin(), info_str.end());
334
- }
335
-
336
- // Optional: peers
337
- auto peers_it = dict.find("peers");
338
- if (peers_it != dict.end() && peers_it->second.is_string()) {
339
- const auto& peers_str = peers_it->second.as_string();
340
-
341
- // Each peer is 6 bytes: 4 byte IP + 2 byte port
342
- for (size_t i = 0; i + 6 <= peers_str.size(); i += 6) {
343
- uint8_t a = static_cast<uint8_t>(peers_str[i]);
344
- uint8_t b = static_cast<uint8_t>(peers_str[i + 1]);
345
- uint8_t c = static_cast<uint8_t>(peers_str[i + 2]);
346
- uint8_t d = static_cast<uint8_t>(peers_str[i + 3]);
347
- uint16_t port = (static_cast<uint16_t>(static_cast<uint8_t>(peers_str[i + 4])) << 8) |
348
- static_cast<uint16_t>(static_cast<uint8_t>(peers_str[i + 5]));
349
-
350
- std::string ip = std::to_string(a) + "." + std::to_string(b) + "." +
351
- std::to_string(c) + "." + std::to_string(d);
352
- data.peers.emplace_back(ip, port);
353
- }
354
- }
355
-
356
- return data;
357
- }
358
-
359
- std::optional<TorrentResumeData> read_resume_data_file(
360
- const std::string& path,
361
- std::string* error_out) {
362
-
363
- std::ifstream file(path, std::ios::binary);
364
- if (!file) {
365
- if (error_out) *error_out = "Failed to open resume file: " + path;
366
- return std::nullopt;
367
- }
368
-
369
- // Read entire file
370
- file.seekg(0, std::ios::end);
371
- size_t size = static_cast<size_t>(file.tellg());
372
- file.seekg(0, std::ios::beg);
373
-
374
- std::vector<uint8_t> buffer(size);
375
- file.read(reinterpret_cast<char*>(buffer.data()), static_cast<std::streamsize>(size));
376
-
377
- if (!file) {
378
- if (error_out) *error_out = "Failed to read resume file: " + path;
379
- return std::nullopt;
380
- }
381
-
382
- LOG_DEBUG("ResumeData", "Read resume file: " + path +
383
- " (" + std::to_string(size) + " bytes)");
384
-
385
- return read_resume_data(buffer, error_out);
386
- }
387
-
388
- //=============================================================================
389
- // Helper Functions
390
- //=============================================================================
391
-
392
- std::string get_resume_file_path(const std::string& save_path, const BtInfoHash& info_hash) {
393
- std::string hash_hex = info_hash_to_hex(info_hash);
394
-
395
- // Use save_path/.resume/{hash}.resume
396
- std::string resume_dir = save_path;
397
- if (!resume_dir.empty() && resume_dir.back() != '/' && resume_dir.back() != '\\') {
398
- resume_dir += '/';
399
- }
400
- resume_dir += ".resume";
401
-
402
- return resume_dir + "/" + hash_hex + ".resume";
403
- }
404
-
405
- bool resume_file_exists(const std::string& save_path, const BtInfoHash& info_hash) {
406
- std::string path = get_resume_file_path(save_path, info_hash);
407
- return file_exists(path.c_str());
408
- }
409
-
410
- } // namespace librats
@@ -1,249 +0,0 @@
1
- #pragma once
2
-
3
- /**
4
- * @file bt_resume_data.h
5
- * @brief BitTorrent torrent resume data for fast resumption
6
- *
7
- * Resume data allows a torrent to quickly resume downloading from where
8
- * it left off, without re-checking all downloaded data. It stores:
9
- * - Which pieces have been verified and are complete
10
- * - Partially downloaded pieces and which blocks are complete
11
- * - Download statistics
12
- * - Configuration settings
13
- *
14
- * This is similar to libtorrent's fast-resume feature.
15
- */
16
-
17
- #include "bt_types.h"
18
- #include "bt_bitfield.h"
19
- #include "bt_torrent_info.h"
20
- #include "bencode.h"
21
-
22
- #include <string>
23
- #include <vector>
24
- #include <map>
25
- #include <cstdint>
26
- #include <optional>
27
-
28
- namespace librats {
29
-
30
- //=============================================================================
31
- // Resume Data Structure
32
- //=============================================================================
33
-
34
- /**
35
- * @brief Stores the state of a partially downloaded piece
36
- *
37
- * For each piece that is partially downloaded, we track which 16KB blocks
38
- * have been written to disk. This allows resuming without losing progress
39
- * on pieces that were in-flight when the client stopped.
40
- */
41
- struct UnfinishedPiece {
42
- uint32_t piece_index; ///< Index of the piece
43
- Bitfield blocks_have; ///< Which blocks are written to disk
44
-
45
- UnfinishedPiece() : piece_index(0) {}
46
- UnfinishedPiece(uint32_t idx, const Bitfield& blocks)
47
- : piece_index(idx), blocks_have(blocks) {}
48
- };
49
-
50
- /**
51
- * @brief Resume data for a torrent
52
- *
53
- * This structure contains all the information needed to resume a torrent
54
- * download without re-checking existing data.
55
- */
56
- struct TorrentResumeData {
57
- //=========================================================================
58
- // Identification
59
- //=========================================================================
60
-
61
- /// Info hash of the torrent (for verification)
62
- BtInfoHash info_hash;
63
-
64
- /// Torrent name (for display)
65
- std::string name;
66
-
67
- //=========================================================================
68
- // Paths
69
- //=========================================================================
70
-
71
- /// Directory where files are saved
72
- std::string save_path;
73
-
74
- //=========================================================================
75
- // Progress - Complete Pieces
76
- //=========================================================================
77
-
78
- /// Bitfield indicating which pieces we have verified and complete
79
- Bitfield have_pieces;
80
-
81
- //=========================================================================
82
- // Progress - Partial Pieces
83
- //=========================================================================
84
-
85
- /// Map of piece index to bitfield of blocks we have for incomplete pieces
86
- /// Key: piece_index, Value: bitfield of blocks that are written to disk
87
- std::map<uint32_t, Bitfield> unfinished_pieces;
88
-
89
- //=========================================================================
90
- // Statistics
91
- //=========================================================================
92
-
93
- /// Total bytes uploaded (all-time)
94
- uint64_t total_uploaded = 0;
95
-
96
- /// Total bytes downloaded (all-time)
97
- uint64_t total_downloaded = 0;
98
-
99
- /// Time spent actively downloading (seconds)
100
- int64_t active_time = 0;
101
-
102
- /// Time spent seeding (seconds)
103
- int64_t seeding_time = 0;
104
-
105
- /// Timestamp when torrent was added (Unix time)
106
- int64_t added_time = 0;
107
-
108
- /// Timestamp when download completed (Unix time, 0 if not complete)
109
- int64_t completed_time = 0;
110
-
111
- //=========================================================================
112
- // Configuration
113
- //=========================================================================
114
-
115
- /// Download pieces in order (for streaming)
116
- bool sequential_download = false;
117
-
118
- /// Maximum connections for this torrent
119
- int max_connections = -1;
120
-
121
- /// Maximum upload slots for this torrent
122
- int max_uploads = -1;
123
-
124
- /// Download rate limit (bytes/sec, -1 = unlimited)
125
- int64_t download_limit = -1;
126
-
127
- /// Upload rate limit (bytes/sec, -1 = unlimited)
128
- int64_t upload_limit = -1;
129
-
130
- //=========================================================================
131
- // Optional: Torrent metadata (for magnet links that completed metadata)
132
- //=========================================================================
133
-
134
- /// Raw info dictionary (optional, for torrents added via magnet)
135
- std::vector<uint8_t> info_dict;
136
-
137
- //=========================================================================
138
- // Optional: Cached peer information
139
- //=========================================================================
140
-
141
- /// List of peers to try connecting to (ip:port pairs)
142
- std::vector<std::pair<std::string, uint16_t>> peers;
143
-
144
- //=========================================================================
145
- // Validation
146
- //=========================================================================
147
-
148
- /**
149
- * @brief Check if resume data is valid for use
150
- * @return true if all required fields are set correctly
151
- */
152
- bool is_valid() const {
153
- // Must have info_hash
154
- bool has_hash = false;
155
- for (uint8_t b : info_hash) {
156
- if (b != 0) { has_hash = true; break; }
157
- }
158
- return has_hash;
159
- }
160
-
161
- /**
162
- * @brief Check if resume data matches a torrent info
163
- * @param info TorrentInfo to check against
164
- * @return true if the resume data is compatible
165
- */
166
- bool matches(const TorrentInfo& info) const {
167
- return info_hash == info.info_hash();
168
- }
169
- };
170
-
171
- //=============================================================================
172
- // Resume Data Serialization (Bencoding)
173
- //=============================================================================
174
-
175
- /**
176
- * @brief Write resume data to a bencoded format
177
- *
178
- * The bencoded format is compatible with libtorrent's resume file format:
179
- * - "file-format": "librats resume file"
180
- * - "file-version": 1
181
- * - "info-hash": 20-byte SHA1 hash
182
- * - "save_path": string
183
- * - "pieces": string (one byte per piece: 0=don't have, 1=have)
184
- * - "unfinished": list of dicts with "piece" and "bitmask"
185
- * - "total_uploaded": integer
186
- * - "total_downloaded": integer
187
- * - etc.
188
- *
189
- * @param data Resume data to serialize
190
- * @return Bencoded data as byte vector
191
- */
192
- std::vector<uint8_t> write_resume_data(const TorrentResumeData& data);
193
-
194
- /**
195
- * @brief Write resume data to a file
196
- *
197
- * @param data Resume data to save
198
- * @param path Path to save file
199
- * @return true on success
200
- */
201
- bool write_resume_data_file(const TorrentResumeData& data, const std::string& path);
202
-
203
- /**
204
- * @brief Read resume data from bencoded format
205
- *
206
- * @param buffer Bencoded data
207
- * @param error_out Optional error message on failure
208
- * @return Resume data if successful, nullopt on error
209
- */
210
- std::optional<TorrentResumeData> read_resume_data(
211
- const std::vector<uint8_t>& buffer,
212
- std::string* error_out = nullptr);
213
-
214
- /**
215
- * @brief Read resume data from a file
216
- *
217
- * @param path Path to resume file
218
- * @param error_out Optional error message on failure
219
- * @return Resume data if successful, nullopt on error
220
- */
221
- std::optional<TorrentResumeData> read_resume_data_file(
222
- const std::string& path,
223
- std::string* error_out = nullptr);
224
-
225
- //=============================================================================
226
- // Resume Data Helper Functions
227
- //=============================================================================
228
-
229
- /**
230
- * @brief Generate default resume file path for a torrent
231
- *
232
- * Creates a path in the form: {save_path}/{info_hash_hex}.resume
233
- *
234
- * @param save_path Torrent save directory
235
- * @param info_hash Torrent info hash
236
- * @return Path to resume file
237
- */
238
- std::string get_resume_file_path(const std::string& save_path, const BtInfoHash& info_hash);
239
-
240
- /**
241
- * @brief Check if a resume file exists for a torrent
242
- *
243
- * @param save_path Torrent save directory
244
- * @param info_hash Torrent info hash
245
- * @return true if resume file exists
246
- */
247
- bool resume_file_exists(const std::string& save_path, const BtInfoHash& info_hash);
248
-
249
- } // namespace librats