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,786 +0,0 @@
1
- #include "bt_piece_picker.h"
2
- #include "logger.h"
3
- #include <algorithm>
4
- #include <random>
5
- #include <chrono>
6
-
7
- namespace librats {
8
-
9
- //=============================================================================
10
- // Constructors
11
- //=============================================================================
12
-
13
- PiecePicker::PiecePicker(uint32_t num_pieces, uint32_t piece_length, uint32_t last_piece_length)
14
- : num_pieces_(num_pieces)
15
- , piece_length_(piece_length)
16
- , last_piece_length_(last_piece_length)
17
- , mode_(PickerMode::RarestFirst)
18
- , endgame_enabled_(true)
19
- , in_endgame_(false)
20
- , max_downloading_pieces_(DEFAULT_MAX_DOWNLOADING_PIECES)
21
- , pieces_(num_pieces)
22
- , num_have_(0)
23
- , num_downloading_(0)
24
- , sequential_cursor_(0) {
25
- }
26
-
27
- PiecePicker::~PiecePicker() = default;
28
-
29
- PiecePicker::PiecePicker(PiecePicker&& other) noexcept
30
- : num_pieces_(other.num_pieces_)
31
- , piece_length_(other.piece_length_)
32
- , last_piece_length_(other.last_piece_length_)
33
- , mode_(other.mode_)
34
- , endgame_enabled_(other.endgame_enabled_)
35
- , in_endgame_(other.in_endgame_)
36
- , max_downloading_pieces_(other.max_downloading_pieces_)
37
- , pieces_(std::move(other.pieces_))
38
- , downloading_(std::move(other.downloading_))
39
- , peer_pieces_(std::move(other.peer_pieces_))
40
- , num_have_(other.num_have_)
41
- , num_downloading_(other.num_downloading_)
42
- , sequential_cursor_(other.sequential_cursor_) {
43
- }
44
-
45
- PiecePicker& PiecePicker::operator=(PiecePicker&& other) noexcept {
46
- if (this != &other) {
47
- std::lock_guard<std::mutex> lock(mutex_);
48
- num_pieces_ = other.num_pieces_;
49
- piece_length_ = other.piece_length_;
50
- last_piece_length_ = other.last_piece_length_;
51
- mode_ = other.mode_;
52
- endgame_enabled_ = other.endgame_enabled_;
53
- in_endgame_ = other.in_endgame_;
54
- max_downloading_pieces_ = other.max_downloading_pieces_;
55
- pieces_ = std::move(other.pieces_);
56
- downloading_ = std::move(other.downloading_);
57
- peer_pieces_ = std::move(other.peer_pieces_);
58
- num_have_ = other.num_have_;
59
- num_downloading_ = other.num_downloading_;
60
- sequential_cursor_ = other.sequential_cursor_;
61
- }
62
- return *this;
63
- }
64
-
65
- //=============================================================================
66
- // Configuration
67
- //=============================================================================
68
-
69
- void PiecePicker::set_mode(PickerMode mode) {
70
- std::lock_guard<std::mutex> lock(mutex_);
71
- mode_ = mode;
72
- }
73
-
74
- PickerMode PiecePicker::mode() const {
75
- std::lock_guard<std::mutex> lock(mutex_);
76
- return mode_;
77
- }
78
-
79
- void PiecePicker::set_piece_priority(uint32_t piece, PiecePriority priority) {
80
- std::lock_guard<std::mutex> lock(mutex_);
81
- if (piece < num_pieces_) {
82
- pieces_[piece].priority = priority;
83
- }
84
- }
85
-
86
- PiecePriority PiecePicker::piece_priority(uint32_t piece) const {
87
- std::lock_guard<std::mutex> lock(mutex_);
88
- if (piece < num_pieces_) {
89
- return pieces_[piece].priority;
90
- }
91
- return PiecePriority::Normal;
92
- }
93
-
94
- void PiecePicker::set_piece_priority_range(uint32_t start, uint32_t end, PiecePriority priority) {
95
- std::lock_guard<std::mutex> lock(mutex_);
96
- end = (std::min)(end, num_pieces_);
97
- for (uint32_t i = start; i < end; ++i) {
98
- pieces_[i].priority = priority;
99
- }
100
- }
101
-
102
- //=============================================================================
103
- // Piece State Management
104
- //=============================================================================
105
-
106
- void PiecePicker::mark_have(uint32_t piece) {
107
- std::lock_guard<std::mutex> lock(mutex_);
108
- if (piece >= num_pieces_) return;
109
-
110
- if (!pieces_[piece].have) {
111
- pieces_[piece].have = true;
112
- ++num_have_;
113
-
114
- // Remove from downloading if present
115
- if (pieces_[piece].downloading) {
116
- remove_downloading(piece);
117
- }
118
- }
119
- }
120
-
121
- void PiecePicker::mark_have_all() {
122
- std::lock_guard<std::mutex> lock(mutex_);
123
-
124
- // Mark all pieces as have
125
- for (uint32_t i = 0; i < num_pieces_; ++i) {
126
- if (!pieces_[i].have) {
127
- pieces_[i].have = true;
128
-
129
- // Clear downloading state if present
130
- if (pieces_[i].downloading) {
131
- pieces_[i].downloading = false;
132
- }
133
- }
134
- }
135
-
136
- // Set count to total
137
- num_have_ = num_pieces_;
138
-
139
- // Clear all downloading state
140
- downloading_.clear();
141
- num_downloading_ = 0;
142
- }
143
-
144
- bool PiecePicker::have_piece(uint32_t piece) const {
145
- std::lock_guard<std::mutex> lock(mutex_);
146
- if (piece >= num_pieces_) return false;
147
- return pieces_[piece].have;
148
- }
149
-
150
- Bitfield PiecePicker::get_have_bitfield() const {
151
- std::lock_guard<std::mutex> lock(mutex_);
152
- Bitfield bf(num_pieces_);
153
- for (uint32_t i = 0; i < num_pieces_; ++i) {
154
- if (pieces_[i].have) {
155
- bf.set_bit(i);
156
- }
157
- }
158
- return bf;
159
- }
160
-
161
- void PiecePicker::set_have_bitfield(const Bitfield& have) {
162
- std::lock_guard<std::mutex> lock(mutex_);
163
- num_have_ = 0;
164
- for (uint32_t i = 0; i < num_pieces_ && i < have.size(); ++i) {
165
- pieces_[i].have = have.get_bit(i);
166
- if (pieces_[i].have) {
167
- ++num_have_;
168
- }
169
- }
170
- }
171
-
172
- uint32_t PiecePicker::num_have() const {
173
- std::lock_guard<std::mutex> lock(mutex_);
174
- return num_have_;
175
- }
176
-
177
- uint32_t PiecePicker::num_want() const {
178
- std::lock_guard<std::mutex> lock(mutex_);
179
- return num_pieces_ - num_have_;
180
- }
181
-
182
- bool PiecePicker::is_complete() const {
183
- std::lock_guard<std::mutex> lock(mutex_);
184
- return num_have_ == num_pieces_;
185
- }
186
-
187
- //=============================================================================
188
- // Peer Availability
189
- //=============================================================================
190
-
191
- void PiecePicker::add_peer(void* peer_id, const Bitfield& bitfield) {
192
- std::lock_guard<std::mutex> lock(mutex_);
193
-
194
- // Store peer's bitfield
195
- peer_pieces_[peer_id] = bitfield;
196
-
197
- // Update availability counts
198
- for (size_t i = 0; i < bitfield.size() && i < num_pieces_; ++i) {
199
- if (bitfield.get_bit(i)) {
200
- ++pieces_[i].availability;
201
- }
202
- }
203
- }
204
-
205
- void PiecePicker::remove_peer(void* peer_id) {
206
- std::lock_guard<std::mutex> lock(mutex_);
207
-
208
- auto it = peer_pieces_.find(peer_id);
209
- if (it == peer_pieces_.end()) return;
210
-
211
- // Decrease availability for pieces this peer had
212
- const Bitfield& bitfield = it->second;
213
- for (size_t i = 0; i < bitfield.size() && i < num_pieces_; ++i) {
214
- if (bitfield.get_bit(i) && pieces_[i].availability > 0) {
215
- --pieces_[i].availability;
216
- }
217
- }
218
-
219
- // Cancel any requests to this peer
220
- for (auto& dp : downloading_) {
221
- for (auto& block : dp.blocks) {
222
- if (block.peer == peer_id && block.state == BlockState::Requested) {
223
- block.state = BlockState::None;
224
- block.peer = nullptr;
225
- }
226
- }
227
- }
228
-
229
- peer_pieces_.erase(it);
230
- }
231
-
232
- void PiecePicker::peer_has_piece(void* peer_id, uint32_t piece) {
233
- std::lock_guard<std::mutex> lock(mutex_);
234
-
235
- if (piece >= num_pieces_) return;
236
-
237
- auto it = peer_pieces_.find(peer_id);
238
- if (it == peer_pieces_.end()) {
239
- // Create empty bitfield for this peer
240
- peer_pieces_[peer_id] = Bitfield(num_pieces_);
241
- it = peer_pieces_.find(peer_id);
242
- }
243
-
244
- if (!it->second.get_bit(piece)) {
245
- it->second.set_bit(piece);
246
- ++pieces_[piece].availability;
247
- }
248
- }
249
-
250
- uint32_t PiecePicker::availability(uint32_t piece) const {
251
- std::lock_guard<std::mutex> lock(mutex_);
252
- if (piece >= num_pieces_) return 0;
253
- return pieces_[piece].availability;
254
- }
255
-
256
- //=============================================================================
257
- // Piece Picking
258
- //=============================================================================
259
-
260
- std::vector<BlockRequest> PiecePicker::pick_pieces(
261
- const Bitfield& peer_bitfield,
262
- size_t num_blocks,
263
- void* peer_id) {
264
-
265
- std::lock_guard<std::mutex> lock(mutex_);
266
- std::vector<BlockRequest> result;
267
-
268
- if (num_blocks == 0) return result;
269
-
270
- // First, try to complete pieces already being downloaded
271
- for (auto& dp : downloading_) {
272
- if (result.size() >= num_blocks) break;
273
-
274
- uint32_t piece = dp.piece_index;
275
- if (!peer_bitfield.get_bit(piece)) continue;
276
-
277
- // Find unrequested blocks in this piece
278
- for (size_t i = 0; i < dp.blocks.size() && result.size() < num_blocks; ++i) {
279
- auto& block = dp.blocks[i];
280
-
281
- bool can_request = false;
282
- if (block.state == BlockState::None) {
283
- can_request = true;
284
- } else if (in_endgame_ && block.state == BlockState::Requested && block.peer != peer_id) {
285
- // In endgame, request from multiple peers
286
- can_request = true;
287
- }
288
-
289
- if (can_request) {
290
- BlockInfo info(piece, static_cast<uint32_t>(i) * BT_BLOCK_SIZE,
291
- block_size(piece, static_cast<uint32_t>(i)));
292
- result.emplace_back(info, peer_id);
293
-
294
- block.state = BlockState::Requested;
295
- block.peer = peer_id;
296
- }
297
- }
298
- }
299
-
300
- // Then, pick new pieces (if we're not at the limit)
301
- // Note: In endgame mode, we ignore the limit to finish faster
302
- while (result.size() < num_blocks) {
303
- // Check if we can start a new piece (respect max_downloading_pieces_ limit)
304
- if (!in_endgame_ && downloading_.size() >= max_downloading_pieces_) {
305
- LOG_DEBUG("PiecePicker", "At max downloading pieces limit (" +
306
- std::to_string(max_downloading_pieces_) + "), not starting new pieces");
307
- break;
308
- }
309
-
310
- uint32_t piece = UINT32_MAX;
311
-
312
- switch (mode_) {
313
- case PickerMode::RarestFirst:
314
- piece = pick_rarest(peer_bitfield);
315
- break;
316
- case PickerMode::Sequential:
317
- piece = pick_sequential(peer_bitfield);
318
- break;
319
- case PickerMode::Random:
320
- piece = pick_random(peer_bitfield);
321
- break;
322
- }
323
-
324
- if (piece == UINT32_MAX) break; // No more pieces available
325
-
326
- // Start downloading this piece
327
- auto* dp = get_or_create_downloading(piece);
328
- if (!dp) break;
329
-
330
- // Pick blocks from this piece
331
- for (size_t i = 0; i < dp->blocks.size() && result.size() < num_blocks; ++i) {
332
- auto& block = dp->blocks[i];
333
- if (block.state == BlockState::None) {
334
- BlockInfo info(piece, static_cast<uint32_t>(i) * BT_BLOCK_SIZE,
335
- block_size(piece, static_cast<uint32_t>(i)));
336
- result.emplace_back(info, peer_id);
337
-
338
- block.state = BlockState::Requested;
339
- block.peer = peer_id;
340
- }
341
- }
342
- }
343
-
344
- return result;
345
- }
346
-
347
- std::optional<uint32_t> PiecePicker::pick_piece(const Bitfield& peer_bitfield) {
348
- std::lock_guard<std::mutex> lock(mutex_);
349
-
350
- uint32_t piece = UINT32_MAX;
351
-
352
- switch (mode_) {
353
- case PickerMode::RarestFirst:
354
- piece = pick_rarest(peer_bitfield);
355
- break;
356
- case PickerMode::Sequential:
357
- piece = pick_sequential(peer_bitfield);
358
- break;
359
- case PickerMode::Random:
360
- piece = pick_random(peer_bitfield);
361
- break;
362
- }
363
-
364
- if (piece == UINT32_MAX) {
365
- return std::nullopt;
366
- }
367
- return piece;
368
- }
369
-
370
- bool PiecePicker::is_interesting(const Bitfield& peer_bitfield) const {
371
- std::lock_guard<std::mutex> lock(mutex_);
372
-
373
- for (uint32_t i = 0; i < num_pieces_; ++i) {
374
- if (!pieces_[i].have &&
375
- pieces_[i].priority != PiecePriority::Skip &&
376
- peer_bitfield.get_bit(i)) {
377
- return true;
378
- }
379
- }
380
- return false;
381
- }
382
-
383
- //=============================================================================
384
- // Block Management
385
- //=============================================================================
386
-
387
- void PiecePicker::mark_requested(const BlockInfo& block, void* peer_id) {
388
- std::lock_guard<std::mutex> lock(mutex_);
389
-
390
- auto* dp = get_or_create_downloading(block.piece_index);
391
- if (!dp) return;
392
-
393
- size_t block_idx = block.offset / BT_BLOCK_SIZE;
394
- if (block_idx < dp->blocks.size()) {
395
- dp->blocks[block_idx].state = BlockState::Requested;
396
- dp->blocks[block_idx].peer = peer_id;
397
- }
398
- }
399
-
400
- void PiecePicker::mark_writing(const BlockInfo& block) {
401
- std::lock_guard<std::mutex> lock(mutex_);
402
-
403
- auto* dp = find_downloading(block.piece_index);
404
- if (!dp) return;
405
-
406
- size_t block_idx = block.offset / BT_BLOCK_SIZE;
407
- if (block_idx < dp->blocks.size()) {
408
- dp->blocks[block_idx].state = BlockState::Writing;
409
- }
410
- }
411
-
412
- bool PiecePicker::mark_finished(const BlockInfo& block) {
413
- std::lock_guard<std::mutex> lock(mutex_);
414
-
415
- auto* dp = find_downloading(block.piece_index);
416
- if (!dp) {
417
- LOG_WARN("PiecePicker", "mark_finished: piece " + std::to_string(block.piece_index) +
418
- " not in downloading list!");
419
- return false;
420
- }
421
-
422
- size_t block_idx = block.offset / BT_BLOCK_SIZE;
423
- if (block_idx >= dp->blocks.size()) {
424
- LOG_WARN("PiecePicker", "mark_finished: block index " + std::to_string(block_idx) +
425
- " >= blocks.size " + std::to_string(dp->blocks.size()));
426
- return false;
427
- }
428
-
429
- dp->blocks[block_idx].state = BlockState::Finished;
430
- dp->blocks[block_idx].peer = nullptr;
431
-
432
- // Check if piece is complete
433
- size_t finished_count = 0;
434
- for (const auto& b : dp->blocks) {
435
- if (b.state == BlockState::Finished) {
436
- ++finished_count;
437
- }
438
- }
439
-
440
- bool complete = (finished_count == dp->blocks.size());
441
-
442
- LOG_DEBUG("PiecePicker", "mark_finished: piece=" + std::to_string(block.piece_index) +
443
- " block=" + std::to_string(block_idx) +
444
- " finished=" + std::to_string(finished_count) + "/" + std::to_string(dp->blocks.size()) +
445
- (complete ? " COMPLETE!" : ""));
446
-
447
- if (complete) {
448
- check_endgame();
449
- }
450
-
451
- return complete;
452
- }
453
-
454
- void PiecePicker::cancel_request(const BlockInfo& block, void* peer_id) {
455
- std::lock_guard<std::mutex> lock(mutex_);
456
-
457
- auto* dp = find_downloading(block.piece_index);
458
- if (!dp) return;
459
-
460
- size_t block_idx = block.offset / BT_BLOCK_SIZE;
461
- if (block_idx < dp->blocks.size()) {
462
- auto& b = dp->blocks[block_idx];
463
- if (b.state == BlockState::Requested && b.peer == peer_id) {
464
- b.state = BlockState::None;
465
- b.peer = nullptr;
466
- }
467
- }
468
- }
469
-
470
- void PiecePicker::cancel_peer_requests(void* peer_id) {
471
- std::lock_guard<std::mutex> lock(mutex_);
472
-
473
- for (auto& dp : downloading_) {
474
- for (auto& b : dp.blocks) {
475
- if (b.peer == peer_id && b.state == BlockState::Requested) {
476
- b.state = BlockState::None;
477
- b.peer = nullptr;
478
- }
479
- }
480
- }
481
- }
482
-
483
- void PiecePicker::abort_download(const BlockInfo& block, void* peer_id) {
484
- std::lock_guard<std::mutex> lock(mutex_);
485
-
486
- auto* dp = find_downloading(block.piece_index);
487
- if (!dp) return;
488
-
489
- // Find the block within the piece
490
- uint32_t block_index = block.offset / BT_BLOCK_SIZE;
491
- if (block_index >= dp->blocks.size()) return;
492
-
493
- auto& b = dp->blocks[block_index];
494
-
495
- // Only abort if it matches the peer (or peer_id is null)
496
- if (b.state == BlockState::Requested &&
497
- (peer_id == nullptr || b.peer == peer_id)) {
498
- b.state = BlockState::None;
499
- b.peer = nullptr;
500
- }
501
- }
502
-
503
- BlockState PiecePicker::block_state(const BlockInfo& block) const {
504
- std::lock_guard<std::mutex> lock(mutex_);
505
-
506
- const auto* dp = find_downloading(block.piece_index);
507
- if (!dp) {
508
- // If piece is marked as have, all blocks are finished
509
- if (block.piece_index < num_pieces_ && pieces_[block.piece_index].have) {
510
- return BlockState::Finished;
511
- }
512
- return BlockState::None;
513
- }
514
-
515
- size_t block_idx = block.offset / BT_BLOCK_SIZE;
516
- if (block_idx < dp->blocks.size()) {
517
- return dp->blocks[block_idx].state;
518
- }
519
- return BlockState::None;
520
- }
521
-
522
- //=============================================================================
523
- // Endgame Mode
524
- //=============================================================================
525
-
526
- bool PiecePicker::in_endgame_mode() const {
527
- std::lock_guard<std::mutex> lock(mutex_);
528
- return in_endgame_;
529
- }
530
-
531
- void PiecePicker::set_endgame_mode(bool enable) {
532
- std::lock_guard<std::mutex> lock(mutex_);
533
- endgame_enabled_ = enable;
534
- if (!enable) {
535
- in_endgame_ = false;
536
- }
537
- }
538
-
539
- void PiecePicker::check_endgame() {
540
- // Called with lock held
541
- if (!endgame_enabled_ || in_endgame_) return;
542
-
543
- // Enter endgame when we have most pieces and only a few blocks left
544
- uint32_t remaining_pieces = num_pieces_ - num_have_;
545
-
546
- // Endgame threshold: less than 5% of pieces remaining, or less than 10 pieces
547
- if (remaining_pieces <= num_pieces_ / 20 || remaining_pieces <= 10) {
548
- in_endgame_ = true;
549
- }
550
- }
551
-
552
- //=============================================================================
553
- // Statistics
554
- //=============================================================================
555
-
556
- size_t PiecePicker::num_downloading() const {
557
- std::lock_guard<std::mutex> lock(mutex_);
558
- return downloading_.size();
559
- }
560
-
561
- std::vector<DownloadingPiece> PiecePicker::downloading_pieces() const {
562
- std::lock_guard<std::mutex> lock(mutex_);
563
-
564
- std::vector<DownloadingPiece> result;
565
- result.reserve(downloading_.size());
566
-
567
- for (const auto& dp : downloading_) {
568
- DownloadingPiece info;
569
- info.piece_index = dp.piece_index;
570
- info.blocks_total = static_cast<uint16_t>(dp.blocks.size());
571
-
572
- for (const auto& b : dp.blocks) {
573
- switch (b.state) {
574
- case BlockState::Requested:
575
- ++info.blocks_requested;
576
- break;
577
- case BlockState::Writing:
578
- ++info.blocks_writing;
579
- break;
580
- case BlockState::Finished:
581
- ++info.blocks_finished;
582
- break;
583
- default:
584
- break;
585
- }
586
- }
587
-
588
- result.push_back(info);
589
- }
590
-
591
- return result;
592
- }
593
-
594
- std::optional<DownloadingPiece> PiecePicker::get_downloading_piece(uint32_t piece) const {
595
- std::lock_guard<std::mutex> lock(mutex_);
596
-
597
- const auto* dp = find_downloading(piece);
598
- if (!dp) return std::nullopt;
599
-
600
- DownloadingPiece info;
601
- info.piece_index = dp->piece_index;
602
- info.blocks_total = static_cast<uint16_t>(dp->blocks.size());
603
-
604
- for (const auto& b : dp->blocks) {
605
- switch (b.state) {
606
- case BlockState::Requested:
607
- ++info.blocks_requested;
608
- break;
609
- case BlockState::Writing:
610
- ++info.blocks_writing;
611
- break;
612
- case BlockState::Finished:
613
- ++info.blocks_finished;
614
- break;
615
- default:
616
- break;
617
- }
618
- }
619
-
620
- return info;
621
- }
622
-
623
- //=============================================================================
624
- // Utility
625
- //=============================================================================
626
-
627
- uint32_t PiecePicker::blocks_in_piece(uint32_t piece) const {
628
- if (piece >= num_pieces_) return 0;
629
-
630
- uint32_t piece_size = (piece == num_pieces_ - 1) ? last_piece_length_ : piece_length_;
631
- return (piece_size + BT_BLOCK_SIZE - 1) / BT_BLOCK_SIZE;
632
- }
633
-
634
- uint32_t PiecePicker::block_size(uint32_t piece, uint32_t block_index) const {
635
- if (piece >= num_pieces_) return 0;
636
-
637
- uint32_t piece_size = (piece == num_pieces_ - 1) ? last_piece_length_ : piece_length_;
638
- uint32_t offset = block_index * BT_BLOCK_SIZE;
639
-
640
- if (offset >= piece_size) return 0;
641
- return (std::min)(BT_BLOCK_SIZE, piece_size - offset);
642
- }
643
-
644
- //=============================================================================
645
- // Internal Methods
646
- //=============================================================================
647
-
648
- uint32_t PiecePicker::pick_rarest(const Bitfield& peer_bitfield) const {
649
- // Find rarest piece that peer has and we don't
650
- uint32_t best_piece = UINT32_MAX;
651
- uint32_t best_availability = UINT32_MAX;
652
-
653
- // Add some randomization among pieces with same availability
654
- std::vector<uint32_t> candidates;
655
-
656
- for (uint32_t i = 0; i < num_pieces_; ++i) {
657
- const auto& piece = pieces_[i];
658
-
659
- // Skip pieces we have, are downloading, or don't want
660
- if (piece.have || piece.downloading || piece.priority == PiecePriority::Skip) {
661
- continue;
662
- }
663
-
664
- // Skip pieces peer doesn't have
665
- if (!peer_bitfield.get_bit(i)) {
666
- continue;
667
- }
668
-
669
- if (piece.availability < best_availability) {
670
- best_availability = piece.availability;
671
- candidates.clear();
672
- candidates.push_back(i);
673
- } else if (piece.availability == best_availability) {
674
- candidates.push_back(i);
675
- }
676
- }
677
-
678
- if (candidates.empty()) {
679
- return UINT32_MAX;
680
- }
681
-
682
- // Return random piece among equally rare ones
683
- if (candidates.size() == 1) {
684
- return candidates[0];
685
- }
686
-
687
- static thread_local std::mt19937 gen(
688
- static_cast<unsigned>(std::chrono::high_resolution_clock::now().time_since_epoch().count()));
689
- std::uniform_int_distribution<size_t> dis(0, candidates.size() - 1);
690
- return candidates[dis(gen)];
691
- }
692
-
693
- uint32_t PiecePicker::pick_sequential(const Bitfield& peer_bitfield) const {
694
- // Start from cursor and find next available piece
695
- for (uint32_t i = 0; i < num_pieces_; ++i) {
696
- uint32_t piece = (sequential_cursor_ + i) % num_pieces_;
697
- const auto& ps = pieces_[piece];
698
-
699
- if (ps.have || ps.downloading || ps.priority == PiecePriority::Skip) {
700
- continue;
701
- }
702
-
703
- if (peer_bitfield.get_bit(piece)) {
704
- return piece;
705
- }
706
- }
707
-
708
- return UINT32_MAX;
709
- }
710
-
711
- uint32_t PiecePicker::pick_random(const Bitfield& peer_bitfield) const {
712
- std::vector<uint32_t> candidates;
713
-
714
- for (uint32_t i = 0; i < num_pieces_; ++i) {
715
- const auto& piece = pieces_[i];
716
-
717
- if (piece.have || piece.downloading || piece.priority == PiecePriority::Skip) {
718
- continue;
719
- }
720
-
721
- if (peer_bitfield.get_bit(i)) {
722
- candidates.push_back(i);
723
- }
724
- }
725
-
726
- if (candidates.empty()) {
727
- return UINT32_MAX;
728
- }
729
-
730
- static thread_local std::mt19937 gen(
731
- static_cast<unsigned>(std::chrono::high_resolution_clock::now().time_since_epoch().count()));
732
- std::uniform_int_distribution<size_t> dis(0, candidates.size() - 1);
733
- return candidates[dis(gen)];
734
- }
735
-
736
- PiecePicker::DownloadingPieceState* PiecePicker::get_or_create_downloading(uint32_t piece) {
737
- // Called with lock held
738
- if (piece >= num_pieces_) return nullptr;
739
-
740
- // Check if already downloading
741
- for (auto& dp : downloading_) {
742
- if (dp.piece_index == piece) {
743
- return &dp;
744
- }
745
- }
746
-
747
- // Create new downloading piece
748
- uint32_t num_blocks = blocks_in_piece(piece);
749
- downloading_.emplace_back(piece, num_blocks);
750
- pieces_[piece].downloading = true;
751
- ++num_downloading_;
752
-
753
- return &downloading_.back();
754
- }
755
-
756
- PiecePicker::DownloadingPieceState* PiecePicker::find_downloading(uint32_t piece) {
757
- for (auto& dp : downloading_) {
758
- if (dp.piece_index == piece) {
759
- return &dp;
760
- }
761
- }
762
- return nullptr;
763
- }
764
-
765
- const PiecePicker::DownloadingPieceState* PiecePicker::find_downloading(uint32_t piece) const {
766
- for (const auto& dp : downloading_) {
767
- if (dp.piece_index == piece) {
768
- return &dp;
769
- }
770
- }
771
- return nullptr;
772
- }
773
-
774
- void PiecePicker::remove_downloading(uint32_t piece) {
775
- // Called with lock held
776
- auto it = std::find_if(downloading_.begin(), downloading_.end(),
777
- [piece](const DownloadingPieceState& dp) { return dp.piece_index == piece; });
778
-
779
- if (it != downloading_.end()) {
780
- pieces_[piece].downloading = false;
781
- downloading_.erase(it);
782
- if (num_downloading_ > 0) --num_downloading_;
783
- }
784
- }
785
-
786
- } // namespace librats