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
@@ -1,677 +0,0 @@
1
- #include "bt_create_torrent.h"
2
- #include "sha1.h"
3
- #include "fs.h"
4
-
5
- #include <fstream>
6
- #include <algorithm>
7
- #include <cstring>
8
-
9
- namespace librats {
10
-
11
- //=============================================================================
12
- // TorrentCreator Implementation
13
- //=============================================================================
14
-
15
- TorrentCreator::TorrentCreator(const std::string& path,
16
- const TorrentCreatorConfig& config)
17
- : base_path_(path)
18
- , comment_(config.comment)
19
- , created_by_(config.created_by)
20
- , creation_date_(config.creation_date)
21
- , is_private_(config.is_private)
22
- , piece_size_(config.piece_size)
23
- , info_hash_valid_(false) {
24
-
25
- // Determine name from path
26
- std::string name = get_filename_from_path(path);
27
- if (name.empty()) {
28
- name = path;
29
- }
30
- files_.set_name(name);
31
-
32
- // Scan files if path exists
33
- if (file_exists(path) || directory_exists(path)) {
34
- if (config.include_hidden_files) {
35
- scan_files(nullptr);
36
- } else {
37
- scan_files([](const std::string& p) {
38
- std::string filename = get_filename_from_path(p);
39
- return filename.empty() || filename[0] != '.';
40
- });
41
- }
42
- }
43
- }
44
-
45
- TorrentCreator::TorrentCreator(FileStorage&& storage,
46
- const std::string& base_path,
47
- const TorrentCreatorConfig& config)
48
- : base_path_(base_path)
49
- , files_(std::move(storage))
50
- , comment_(config.comment)
51
- , created_by_(config.created_by)
52
- , creation_date_(config.creation_date)
53
- , is_private_(config.is_private)
54
- , piece_size_(config.piece_size)
55
- , info_hash_valid_(false) {
56
- }
57
-
58
- //=============================================================================
59
- // File Management
60
- //=============================================================================
61
-
62
- size_t TorrentCreator::scan_files(FileFilterCallback filter) {
63
- // Clear existing files but keep name
64
- std::string name = files_.name();
65
- files_ = FileStorage();
66
- files_.set_name(name);
67
- piece_hashes_.clear();
68
- info_hash_valid_ = false;
69
-
70
- if (is_directory(base_path_.c_str())) {
71
- scan_directory(base_path_, "", filter);
72
- } else if (file_exists(base_path_.c_str())) {
73
- // Single file
74
- int64_t size = get_file_size(base_path_.c_str());
75
- if (size >= 0) {
76
- std::string filename = get_filename_from_path(base_path_);
77
- files_.add_file(filename, size);
78
- }
79
- }
80
-
81
- return files_.num_files();
82
- }
83
-
84
- void TorrentCreator::scan_directory(const std::string& dir_path,
85
- const std::string& relative_prefix,
86
- FileFilterCallback filter) {
87
- std::vector<DirectoryEntry> entries;
88
- if (!list_directory(dir_path.c_str(), entries)) {
89
- return;
90
- }
91
-
92
- // Sort entries for consistent ordering
93
- std::sort(entries.begin(), entries.end(),
94
- [](const DirectoryEntry& a, const DirectoryEntry& b) {
95
- return a.name < b.name;
96
- });
97
-
98
- for (const auto& entry : entries) {
99
- // Skip . and ..
100
- if (entry.name == "." || entry.name == "..") {
101
- continue;
102
- }
103
-
104
- std::string full_path = combine_paths(dir_path, entry.name);
105
- std::string relative_path = relative_prefix.empty()
106
- ? entry.name
107
- : relative_prefix + "/" + entry.name;
108
-
109
- // Apply filter
110
- if (filter && !filter(full_path)) {
111
- continue;
112
- }
113
-
114
- if (entry.is_directory) {
115
- // Recurse into directory
116
- scan_directory(full_path, relative_path, filter);
117
- } else {
118
- // Add file
119
- files_.add_file(relative_path, static_cast<int64_t>(entry.size));
120
- }
121
- }
122
- }
123
-
124
- bool TorrentCreator::add_file(const std::string& relative_path, int64_t size) {
125
- if (relative_path.empty() || size < 0) {
126
- return false;
127
- }
128
-
129
- files_.add_file(relative_path, size);
130
- piece_hashes_.clear();
131
- info_hash_valid_ = false;
132
- return true;
133
- }
134
-
135
- //=============================================================================
136
- // Properties
137
- //=============================================================================
138
-
139
- void TorrentCreator::set_name(const std::string& name) {
140
- files_.set_name(name);
141
- info_hash_valid_ = false;
142
- }
143
-
144
- void TorrentCreator::set_piece_size(uint32_t size) {
145
- // Validate piece size (must be power of 2, >= 16 KiB)
146
- if (size > 0) {
147
- if (size < 16 * 1024) {
148
- size = 16 * 1024;
149
- }
150
- // Round up to power of 2
151
- uint32_t power = 1;
152
- while (power < size) {
153
- power *= 2;
154
- }
155
- size = power;
156
- }
157
-
158
- piece_size_ = size;
159
- piece_hashes_.clear();
160
- info_hash_valid_ = false;
161
- }
162
-
163
- uint32_t TorrentCreator::auto_detect_piece_size() const {
164
- int64_t total = total_size();
165
-
166
- // Size thresholds and corresponding piece sizes
167
- // Based on libtorrent's algorithm
168
- static const struct {
169
- int64_t threshold;
170
- uint32_t piece_size;
171
- } size_table[] = {
172
- { 2684355LL, 16 * 1024 }, // -> 16 KiB
173
- { 10737418LL, 32 * 1024 }, // -> 32 KiB
174
- { 42949673LL, 64 * 1024 }, // -> 64 KiB
175
- { 171798692LL, 128 * 1024 }, // -> 128 KiB
176
- { 687194767LL, 256 * 1024 }, // -> 256 KiB
177
- { 2748779069LL, 512 * 1024 }, // -> 512 KiB
178
- { 10995116278LL, 1024 * 1024 }, // -> 1 MiB
179
- { 43980465111LL, 2 * 1024 * 1024 }, // -> 2 MiB
180
- { 175921860444LL, 4 * 1024 * 1024 }, // -> 4 MiB
181
- { 703687441777LL, 8 * 1024 * 1024 }, // -> 8 MiB
182
- { 2814749767106LL, 16 * 1024 * 1024 } // -> 16 MiB
183
- };
184
-
185
- for (const auto& entry : size_table) {
186
- if (total < entry.threshold) {
187
- return entry.piece_size;
188
- }
189
- }
190
-
191
- return 16 * 1024 * 1024; // Max 16 MiB
192
- }
193
-
194
- //=============================================================================
195
- // Trackers and Seeds
196
- //=============================================================================
197
-
198
- void TorrentCreator::add_tracker(const std::string& url, int tier) {
199
- if (url.empty()) return;
200
-
201
- // Check for duplicates
202
- for (const auto& t : trackers_) {
203
- if (t.first == url) return;
204
- }
205
-
206
- trackers_.emplace_back(url, tier);
207
-
208
- // Sort by tier
209
- std::sort(trackers_.begin(), trackers_.end(),
210
- [](const auto& a, const auto& b) { return a.second < b.second; });
211
- }
212
-
213
- std::vector<std::string> TorrentCreator::trackers() const {
214
- std::vector<std::string> result;
215
- result.reserve(trackers_.size());
216
- for (const auto& t : trackers_) {
217
- result.push_back(t.first);
218
- }
219
- return result;
220
- }
221
-
222
- void TorrentCreator::add_url_seed(const std::string& url) {
223
- if (!url.empty()) {
224
- url_seeds_.push_back(url);
225
- }
226
- }
227
-
228
- void TorrentCreator::add_http_seed(const std::string& url) {
229
- if (!url.empty()) {
230
- http_seeds_.push_back(url);
231
- }
232
- }
233
-
234
- void TorrentCreator::add_dht_node(const std::string& host, uint16_t port) {
235
- if (!host.empty() && port > 0) {
236
- dht_nodes_.emplace_back(host, port);
237
- }
238
- }
239
-
240
- //=============================================================================
241
- // Piece Hashing
242
- //=============================================================================
243
-
244
- bool TorrentCreator::set_piece_hashes(PieceHashProgressCallback progress_callback,
245
- TorrentCreateError* error) {
246
- if (files_.num_files() == 0) {
247
- if (error) error->message = "No files to hash";
248
- return false;
249
- }
250
-
251
- if (total_size() == 0) {
252
- if (error) error->message = "Total size is zero";
253
- return false;
254
- }
255
-
256
- // Determine piece size
257
- uint32_t psize = piece_size_;
258
- if (psize == 0) {
259
- psize = auto_detect_piece_size();
260
- }
261
- piece_size_ = psize;
262
-
263
- // Finalize file storage with piece size
264
- files_.set_piece_length(psize);
265
- files_.finalize();
266
-
267
- uint32_t num_pcs = files_.num_pieces();
268
- piece_hashes_.clear();
269
- piece_hashes_.reserve(num_pcs * 20);
270
-
271
- // Buffer for reading file data
272
- std::vector<uint8_t> piece_buffer(psize);
273
-
274
- // Current position in file storage
275
- uint32_t current_piece = 0;
276
- uint32_t piece_offset = 0;
277
-
278
- // For each file
279
- for (size_t file_idx = 0; file_idx < files_.num_files(); ++file_idx) {
280
- const FileEntry& entry = files_.file_at(file_idx);
281
-
282
- // Build full path to file
283
- std::string file_path;
284
- if (is_directory(base_path_.c_str())) {
285
- file_path = combine_paths(base_path_, entry.path);
286
- } else {
287
- file_path = base_path_;
288
- }
289
-
290
- // Open file
291
- std::ifstream file(file_path, std::ios::binary);
292
- if (!file) {
293
- if (error) error->message = "Failed to open file: " + file_path;
294
- return false;
295
- }
296
-
297
- int64_t remaining = entry.size;
298
- while (remaining > 0) {
299
- // How much to read for current piece
300
- uint32_t space_in_piece = psize - piece_offset;
301
- uint32_t to_read = static_cast<uint32_t>(std::min(static_cast<int64_t>(space_in_piece), remaining));
302
-
303
- // Read data
304
- if (!file.read(reinterpret_cast<char*>(piece_buffer.data() + piece_offset), to_read)) {
305
- if (error) error->message = "Failed to read file: " + file_path;
306
- return false;
307
- }
308
-
309
- piece_offset += to_read;
310
- remaining -= to_read;
311
-
312
- // If piece is complete, hash it
313
- if (piece_offset == psize) {
314
- SHA1 hasher;
315
- hasher.update(piece_buffer.data(), psize);
316
- std::string hex_hash = hasher.finalize();
317
-
318
- // Convert hex to bytes
319
- for (size_t i = 0; i < 40; i += 2) {
320
- uint8_t byte = static_cast<uint8_t>(
321
- std::stoul(hex_hash.substr(i, 2), nullptr, 16));
322
- piece_hashes_.push_back(byte);
323
- }
324
-
325
- ++current_piece;
326
- piece_offset = 0;
327
-
328
- // Progress callback
329
- if (progress_callback) {
330
- progress_callback(current_piece, num_pcs);
331
- }
332
- }
333
- }
334
- }
335
-
336
- // Hash final partial piece if any
337
- if (piece_offset > 0) {
338
- SHA1 hasher;
339
- hasher.update(piece_buffer.data(), piece_offset);
340
- std::string hex_hash = hasher.finalize();
341
-
342
- // Convert hex to bytes
343
- for (size_t i = 0; i < 40; i += 2) {
344
- uint8_t byte = static_cast<uint8_t>(
345
- std::stoul(hex_hash.substr(i, 2), nullptr, 16));
346
- piece_hashes_.push_back(byte);
347
- }
348
-
349
- ++current_piece;
350
-
351
- // Final progress callback
352
- if (progress_callback) {
353
- progress_callback(current_piece, num_pcs);
354
- }
355
- }
356
-
357
- info_hash_valid_ = false;
358
- return true;
359
- }
360
-
361
- //=============================================================================
362
- // Generation
363
- //=============================================================================
364
-
365
- BencodeValue TorrentCreator::build_info_dict() const {
366
- BencodeValue info = BencodeValue::create_dict();
367
-
368
- // Name (required)
369
- info["name"] = BencodeValue(files_.name());
370
-
371
- // Piece length (required)
372
- info["piece length"] = BencodeValue(static_cast<int64_t>(piece_size_));
373
-
374
- // Pieces (required) - concatenated SHA-1 hashes
375
- std::string pieces_str(piece_hashes_.begin(), piece_hashes_.end());
376
- info["pieces"] = BencodeValue(pieces_str);
377
-
378
- // Private flag
379
- if (is_private_) {
380
- info["private"] = BencodeValue(static_cast<int64_t>(1));
381
- }
382
-
383
- // File(s)
384
- if (files_.num_files() == 1) {
385
- // Single-file mode
386
- info["length"] = BencodeValue(files_.file_at(0).size);
387
- } else {
388
- // Multi-file mode
389
- BencodeValue files_list = BencodeValue::create_list();
390
-
391
- for (size_t i = 0; i < files_.num_files(); ++i) {
392
- const FileEntry& entry = files_.file_at(i);
393
-
394
- BencodeValue file_dict = BencodeValue::create_dict();
395
- file_dict["length"] = BencodeValue(entry.size);
396
-
397
- // Path components
398
- BencodeValue path_list = BencodeValue::create_list();
399
- std::string path = entry.path;
400
-
401
- // Split path by /
402
- size_t pos = 0;
403
- while (pos < path.size()) {
404
- size_t next = path.find('/', pos);
405
- if (next == std::string::npos) {
406
- next = path.size();
407
- }
408
- if (next > pos) {
409
- path_list.push_back(BencodeValue(path.substr(pos, next - pos)));
410
- }
411
- pos = next + 1;
412
- }
413
-
414
- file_dict["path"] = std::move(path_list);
415
- files_list.push_back(std::move(file_dict));
416
- }
417
-
418
- info["files"] = std::move(files_list);
419
- }
420
-
421
- return info;
422
- }
423
-
424
- BencodeValue TorrentCreator::build_torrent_dict() const {
425
- BencodeValue dict = BencodeValue::create_dict();
426
-
427
- // Info dictionary (required)
428
- dict["info"] = build_info_dict();
429
-
430
- // Announce (primary tracker)
431
- if (!trackers_.empty()) {
432
- dict["announce"] = BencodeValue(trackers_[0].first);
433
- }
434
-
435
- // Announce-list (multi-tracker)
436
- if (trackers_.size() > 1) {
437
- BencodeValue announce_list = BencodeValue::create_list();
438
- BencodeValue current_tier = BencodeValue::create_list();
439
- int current_tier_num = trackers_[0].second;
440
-
441
- for (const auto& tracker : trackers_) {
442
- if (tracker.second != current_tier_num) {
443
- announce_list.push_back(std::move(current_tier));
444
- current_tier = BencodeValue::create_list();
445
- current_tier_num = tracker.second;
446
- }
447
- current_tier.push_back(BencodeValue(tracker.first));
448
- }
449
- announce_list.push_back(std::move(current_tier));
450
-
451
- dict["announce-list"] = std::move(announce_list);
452
- }
453
-
454
- // Comment
455
- if (!comment_.empty()) {
456
- dict["comment"] = BencodeValue(comment_);
457
- }
458
-
459
- // Created by
460
- if (!created_by_.empty()) {
461
- dict["created by"] = BencodeValue(created_by_);
462
- }
463
-
464
- // Creation date
465
- if (creation_date_ != 0) {
466
- dict["creation date"] = BencodeValue(static_cast<int64_t>(creation_date_));
467
- }
468
-
469
- // URL seeds
470
- if (!url_seeds_.empty()) {
471
- if (url_seeds_.size() == 1) {
472
- dict["url-list"] = BencodeValue(url_seeds_[0]);
473
- } else {
474
- BencodeValue list = BencodeValue::create_list();
475
- for (const auto& seed : url_seeds_) {
476
- list.push_back(BencodeValue(seed));
477
- }
478
- dict["url-list"] = std::move(list);
479
- }
480
- }
481
-
482
- // HTTP seeds
483
- if (!http_seeds_.empty()) {
484
- if (http_seeds_.size() == 1) {
485
- dict["httpseeds"] = BencodeValue(http_seeds_[0]);
486
- } else {
487
- BencodeValue list = BencodeValue::create_list();
488
- for (const auto& seed : http_seeds_) {
489
- list.push_back(BencodeValue(seed));
490
- }
491
- dict["httpseeds"] = std::move(list);
492
- }
493
- }
494
-
495
- // DHT nodes
496
- if (!dht_nodes_.empty()) {
497
- BencodeValue nodes = BencodeValue::create_list();
498
- for (const auto& node : dht_nodes_) {
499
- BencodeValue node_entry = BencodeValue::create_list();
500
- node_entry.push_back(BencodeValue(node.first));
501
- node_entry.push_back(BencodeValue(static_cast<int64_t>(node.second)));
502
- nodes.push_back(std::move(node_entry));
503
- }
504
- dict["nodes"] = std::move(nodes);
505
- }
506
-
507
- return dict;
508
- }
509
-
510
- std::vector<uint8_t> TorrentCreator::generate(TorrentCreateError* error) const {
511
- if (piece_hashes_.empty()) {
512
- if (error) error->message = "Piece hashes not computed. Call set_piece_hashes() first.";
513
- return {};
514
- }
515
-
516
- if (files_.num_files() == 0) {
517
- if (error) error->message = "No files in torrent";
518
- return {};
519
- }
520
-
521
- BencodeValue torrent = build_torrent_dict();
522
- return torrent.encode();
523
- }
524
-
525
- bool TorrentCreator::save_to_file(const std::string& output_path,
526
- TorrentCreateError* error) const {
527
- auto data = generate(error);
528
- if (data.empty()) {
529
- return false;
530
- }
531
-
532
- std::ofstream file(output_path, std::ios::binary);
533
- if (!file) {
534
- if (error) error->message = "Failed to open output file: " + output_path;
535
- return false;
536
- }
537
-
538
- if (!file.write(reinterpret_cast<const char*>(data.data()), data.size())) {
539
- if (error) error->message = "Failed to write output file: " + output_path;
540
- return false;
541
- }
542
-
543
- return true;
544
- }
545
-
546
- std::optional<TorrentInfo> TorrentCreator::generate_torrent_info(TorrentCreateError* error) const {
547
- auto data = generate(error);
548
- if (data.empty()) {
549
- return std::nullopt;
550
- }
551
-
552
- TorrentParseError parse_error;
553
- auto result = TorrentInfo::from_bytes(data, &parse_error);
554
- if (!result && error) {
555
- error->message = parse_error.message;
556
- }
557
- return result;
558
- }
559
-
560
- BtInfoHash TorrentCreator::info_hash() const {
561
- if (info_hash_valid_) {
562
- return cached_info_hash_;
563
- }
564
-
565
- if (piece_hashes_.empty()) {
566
- return BtInfoHash{};
567
- }
568
-
569
- BencodeValue info_dict = build_info_dict();
570
- std::vector<uint8_t> info_bytes = info_dict.encode();
571
-
572
- SHA1 hasher;
573
- hasher.update(info_bytes.data(), info_bytes.size());
574
- std::string hex_hash = hasher.finalize();
575
-
576
- cached_info_hash_ = hex_to_info_hash(hex_hash);
577
- info_hash_valid_ = true;
578
-
579
- return cached_info_hash_;
580
- }
581
-
582
- std::string TorrentCreator::info_hash_hex() const {
583
- BtInfoHash hash = info_hash();
584
- return info_hash_to_hex(hash);
585
- }
586
-
587
- //=============================================================================
588
- // Convenience Functions
589
- //=============================================================================
590
-
591
- size_t add_files(FileStorage& storage, const std::string& path,
592
- FileFilterCallback filter) {
593
- size_t count = 0;
594
-
595
- if (is_directory(path.c_str())) {
596
- std::vector<DirectoryEntry> entries;
597
- if (!list_directory(path.c_str(), entries)) {
598
- return 0;
599
- }
600
-
601
- std::sort(entries.begin(), entries.end(),
602
- [](const DirectoryEntry& a, const DirectoryEntry& b) {
603
- return a.name < b.name;
604
- });
605
-
606
- for (const auto& entry : entries) {
607
- if (entry.name == "." || entry.name == "..") continue;
608
-
609
- std::string full_path = combine_paths(path, entry.name);
610
-
611
- if (filter && !filter(full_path)) continue;
612
-
613
- if (entry.is_directory) {
614
- count += add_files(storage, full_path, filter);
615
- } else {
616
- storage.add_file(entry.name, static_cast<int64_t>(entry.size));
617
- ++count;
618
- }
619
- }
620
- } else if (file_exists(path.c_str())) {
621
- if (!filter || filter(path)) {
622
- int64_t size = get_file_size(path.c_str());
623
- std::string filename = get_filename_from_path(path);
624
- storage.add_file(filename, size);
625
- ++count;
626
- }
627
- }
628
-
629
- return count;
630
- }
631
-
632
- bool create_torrent(const std::string& path,
633
- const std::string& output_path,
634
- const std::vector<std::string>& trackers,
635
- const std::string& comment,
636
- PieceHashProgressCallback progress_callback,
637
- TorrentCreateError* error) {
638
- TorrentCreatorConfig config;
639
- config.comment = comment;
640
- config.created_by = "librats";
641
-
642
- TorrentCreator creator(path, config);
643
-
644
- for (const auto& tracker : trackers) {
645
- creator.add_tracker(tracker);
646
- }
647
-
648
- if (!creator.set_piece_hashes(progress_callback, error)) {
649
- return false;
650
- }
651
-
652
- return creator.save_to_file(output_path, error);
653
- }
654
-
655
- std::vector<uint8_t> create_torrent_data(const std::string& path,
656
- const std::vector<std::string>& trackers,
657
- const std::string& comment,
658
- PieceHashProgressCallback progress_callback,
659
- TorrentCreateError* error) {
660
- TorrentCreatorConfig config;
661
- config.comment = comment;
662
- config.created_by = "librats";
663
-
664
- TorrentCreator creator(path, config);
665
-
666
- for (const auto& tracker : trackers) {
667
- creator.add_tracker(tracker);
668
- }
669
-
670
- if (!creator.set_piece_hashes(progress_callback, error)) {
671
- return {};
672
- }
673
-
674
- return creator.generate(error);
675
- }
676
-
677
- } // namespace librats