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.
- package/README.md +145 -331
- package/binding.gyp +16 -3
- package/lib/index.d.ts +288 -696
- package/lib/index.js +407 -44
- package/native-src/3rdparty/android/ifaddrs-android.c +1 -0
- package/native-src/3rdparty/android/ifaddrs-android.h +1 -0
- package/native-src/CMakeLists.txt +404 -179
- package/native-src/LICENSE +1 -1
- package/native-src/src/librats/bindings/rats.cpp +762 -0
- package/native-src/src/librats/bindings/rats.h +380 -0
- package/native-src/src/librats/bittorrent/bencode.cpp +437 -0
- package/native-src/src/librats/bittorrent/bencode.h +176 -0
- package/native-src/src/librats/bittorrent/bitfield.cpp +97 -0
- package/native-src/src/librats/bittorrent/bitfield.h +76 -0
- package/native-src/src/librats/bittorrent/byte_io.h +58 -0
- package/native-src/src/librats/bittorrent/choker.cpp +25 -0
- package/native-src/src/librats/bittorrent/choker.h +46 -0
- package/native-src/src/librats/bittorrent/client.cpp +413 -0
- package/native-src/src/librats/bittorrent/client.h +227 -0
- package/native-src/src/librats/bittorrent/disk_io.cpp +209 -0
- package/native-src/src/librats/bittorrent/disk_io.h +150 -0
- package/native-src/src/librats/bittorrent/extensions.cpp +191 -0
- package/native-src/src/librats/bittorrent/extensions.h +94 -0
- package/native-src/src/librats/bittorrent/file_storage.cpp +77 -0
- package/native-src/src/librats/bittorrent/file_storage.h +79 -0
- package/native-src/src/librats/bittorrent/log.h +42 -0
- package/native-src/src/librats/bittorrent/magnet_uri.cpp +98 -0
- package/native-src/src/librats/bittorrent/magnet_uri.h +35 -0
- package/native-src/src/librats/bittorrent/peer_connection.cpp +502 -0
- package/native-src/src/librats/bittorrent/peer_connection.h +194 -0
- package/native-src/src/librats/bittorrent/peer_list.cpp +68 -0
- package/native-src/src/librats/bittorrent/peer_list.h +75 -0
- package/native-src/src/librats/bittorrent/piece_picker.cpp +352 -0
- package/native-src/src/librats/bittorrent/piece_picker.h +201 -0
- package/native-src/src/librats/bittorrent/reactor.cpp +97 -0
- package/native-src/src/librats/bittorrent/reactor.h +89 -0
- package/native-src/src/librats/bittorrent/resume_data.cpp +72 -0
- package/native-src/src/librats/bittorrent/resume_data.h +41 -0
- package/native-src/src/librats/bittorrent/store_buffer.cpp +48 -0
- package/native-src/src/librats/bittorrent/store_buffer.h +47 -0
- package/native-src/src/librats/bittorrent/torrent.cpp +870 -0
- package/native-src/src/librats/bittorrent/torrent.h +260 -0
- package/native-src/src/librats/bittorrent/torrent_creator.cpp +129 -0
- package/native-src/src/librats/bittorrent/torrent_creator.h +58 -0
- package/native-src/src/librats/bittorrent/torrent_info.cpp +314 -0
- package/native-src/src/librats/bittorrent/torrent_info.h +118 -0
- package/native-src/src/librats/bittorrent/tracker.cpp +374 -0
- package/native-src/src/librats/bittorrent/tracker.h +108 -0
- package/native-src/src/librats/bittorrent/types.cpp +206 -0
- package/native-src/src/librats/bittorrent/types.h +86 -0
- package/native-src/src/librats/core/address.cpp +35 -0
- package/native-src/src/librats/core/address.h +78 -0
- package/native-src/src/librats/core/bytes.h +69 -0
- package/native-src/src/librats/core/chained_send_buffer.cpp +172 -0
- package/native-src/src/librats/core/chained_send_buffer.h +183 -0
- package/native-src/src/librats/core/endpoint_parse.cpp +41 -0
- package/native-src/src/librats/core/endpoint_parse.h +31 -0
- package/native-src/src/librats/core/event_bus.h +70 -0
- package/native-src/src/librats/core/host_endpoint.h +56 -0
- package/native-src/src/{io_poller.cpp → librats/core/io_poller.cpp} +520 -65
- package/native-src/src/{io_poller.h → librats/core/io_poller.h} +12 -6
- package/native-src/src/librats/core/ip_address.cpp +120 -0
- package/native-src/src/librats/core/ip_address.h +109 -0
- package/native-src/src/librats/core/mpsc_queue.h +47 -0
- package/native-src/src/librats/core/notifier.h +74 -0
- package/native-src/src/librats/core/receive_buffer.cpp +219 -0
- package/native-src/src/librats/core/receive_buffer.h +171 -0
- package/native-src/src/librats/core/service_registry.h +58 -0
- package/native-src/src/{socket.cpp → librats/core/socket.cpp} +625 -118
- package/native-src/src/librats/core/socket.h +496 -0
- package/native-src/src/librats/core/timer_queue.h +105 -0
- package/native-src/src/librats/core/types.cpp +43 -0
- package/native-src/src/librats/core/types.h +103 -0
- package/native-src/src/librats/core/wakeup_pipe.h +83 -0
- package/native-src/src/{crypto → librats/crypto}/blake2_endian.h +21 -23
- package/native-src/src/{crypto → librats/crypto}/blake2b.c +34 -33
- package/native-src/src/{crypto → librats/crypto}/blake2b.h +7 -6
- package/native-src/src/{crypto → librats/crypto}/blake2s.c +55 -54
- package/native-src/src/{crypto → librats/crypto}/blake2s.h +13 -12
- package/native-src/src/{crypto → librats/crypto}/chacha.c +22 -21
- package/native-src/src/{crypto → librats/crypto}/chacha.h +14 -13
- package/native-src/src/{crypto → librats/crypto}/chachapoly.c +56 -56
- package/native-src/src/{crypto → librats/crypto}/chachapoly.h +24 -17
- package/native-src/src/{crc32.cpp → librats/crypto/crc32.cpp} +1 -1
- package/native-src/src/{crc32.h → librats/crypto/crc32.h} +3 -1
- package/native-src/src/{crypto → librats/crypto}/curve25519.c +6 -4
- package/native-src/src/{crypto → librats/crypto}/curve25519.h +6 -3
- package/native-src/src/librats/crypto/hkdf.c +266 -0
- package/native-src/src/{crypto → librats/crypto}/hkdf.h +19 -19
- package/native-src/src/{noise.cpp → librats/crypto/noise.cpp} +84 -73
- package/native-src/src/{noise.h → librats/crypto/noise.h} +18 -8
- package/native-src/src/{crypto → librats/crypto}/poly1305.c +47 -46
- package/native-src/src/librats/crypto/poly1305.h +37 -0
- package/native-src/src/{sha1.cpp → librats/crypto/sha1.cpp} +33 -1
- package/native-src/src/{sha1.h → librats/crypto/sha1.h} +14 -6
- package/native-src/src/{crypto → librats/crypto}/sha256.c +15 -14
- package/native-src/src/{crypto → librats/crypto}/sha256.h +8 -7
- package/native-src/src/{crypto → librats/crypto}/sha512.c +15 -14
- package/native-src/src/{crypto → librats/crypto}/sha512.h +8 -7
- package/native-src/src/librats/dht/announce.cpp +37 -0
- package/native-src/src/librats/dht/announce.h +41 -0
- package/native-src/src/librats/dht/bep42.cpp +109 -0
- package/native-src/src/librats/dht/bep42.h +48 -0
- package/native-src/src/librats/dht/dht.cpp +501 -0
- package/native-src/src/librats/dht/dht.h +119 -0
- package/native-src/src/librats/dht/dht_runner.cpp +103 -0
- package/native-src/src/librats/dht/dht_runner.h +71 -0
- package/native-src/src/librats/dht/dos_blocker.cpp +42 -0
- package/native-src/src/librats/dht/dos_blocker.h +47 -0
- package/native-src/src/librats/dht/find_peers.cpp +52 -0
- package/native-src/src/librats/dht/find_peers.h +73 -0
- package/native-src/src/librats/dht/id.h +167 -0
- package/native-src/src/{krpc.cpp → librats/dht/krpc.cpp} +32 -81
- package/native-src/src/{krpc.h → librats/dht/krpc.h} +19 -23
- package/native-src/src/librats/dht/log.h +38 -0
- package/native-src/src/librats/dht/node.cpp +473 -0
- package/native-src/src/librats/dht/node.h +164 -0
- package/native-src/src/librats/dht/node_entry.h +81 -0
- package/native-src/src/librats/dht/observer.h +72 -0
- package/native-src/src/librats/dht/persistence.cpp +90 -0
- package/native-src/src/librats/dht/persistence.h +32 -0
- package/native-src/src/librats/dht/routing_table.cpp +559 -0
- package/native-src/src/librats/dht/routing_table.h +185 -0
- package/native-src/src/librats/dht/rpc_manager.cpp +127 -0
- package/native-src/src/librats/dht/rpc_manager.h +77 -0
- package/native-src/src/librats/dht/storage.cpp +92 -0
- package/native-src/src/librats/dht/storage.h +74 -0
- package/native-src/src/librats/dht/transport.h +27 -0
- package/native-src/src/librats/dht/traversal.cpp +326 -0
- package/native-src/src/librats/dht/traversal.h +120 -0
- package/native-src/src/librats/dht/udp_transport.cpp +49 -0
- package/native-src/src/librats/dht/udp_transport.h +51 -0
- package/native-src/src/librats/mdns/log.h +22 -0
- package/native-src/src/{mdns.cpp → librats/mdns/mdns.cpp} +75 -40
- package/native-src/src/{mdns.h → librats/mdns/mdns.h} +9 -8
- package/native-src/src/{natpmp.cpp → librats/nat/natpmp.cpp} +12 -9
- package/native-src/src/{natpmp.h → librats/nat/natpmp.h} +3 -3
- package/native-src/src/{port_mapping.h → librats/nat/port_mapping.h} +3 -2
- package/native-src/src/{stun.cpp → librats/nat/stun.cpp} +4 -4
- package/native-src/src/{stun.h → librats/nat/stun.h} +1 -1
- package/native-src/src/{upnp.cpp → librats/nat/upnp.cpp} +6 -6
- package/native-src/src/{upnp.h → librats/nat/upnp.h} +2 -2
- package/native-src/src/librats/node/circuit_service.h +84 -0
- package/native-src/src/librats/node/config.h +110 -0
- package/native-src/src/librats/node/dial_service.h +54 -0
- package/native-src/src/librats/node/dialer.cpp +264 -0
- package/native-src/src/librats/node/dialer.h +188 -0
- package/native-src/src/librats/node/host_events.h +26 -0
- package/native-src/src/librats/node/identify.cpp +130 -0
- package/native-src/src/librats/node/identify.h +71 -0
- package/native-src/src/librats/node/nat_status.cpp +103 -0
- package/native-src/src/librats/node/nat_status.h +118 -0
- package/native-src/src/librats/node/node.cpp +865 -0
- package/native-src/src/librats/node/node.h +344 -0
- package/native-src/src/librats/node/node_context.h +33 -0
- package/native-src/src/librats/node/peer_network.h +91 -0
- package/native-src/src/librats/peer/peer.h +49 -0
- package/native-src/src/librats/peer/peer_book.cpp +181 -0
- package/native-src/src/librats/peer/peer_book.h +88 -0
- package/native-src/src/librats/peer/peer_id.cpp +72 -0
- package/native-src/src/librats/peer/peer_id.h +62 -0
- package/native-src/src/librats/peer/peer_info.h +37 -0
- package/native-src/src/librats/peer/peer_table.cpp +170 -0
- package/native-src/src/librats/peer/peer_table.h +148 -0
- package/native-src/src/librats/security/handshaker.h +66 -0
- package/native-src/src/librats/security/identity.h +43 -0
- package/native-src/src/librats/security/noise_security.cpp +122 -0
- package/native-src/src/librats/security/noise_security.h +37 -0
- package/native-src/src/librats/security/plaintext_security.h +106 -0
- package/native-src/src/librats/security/session.h +37 -0
- package/native-src/src/{storage.cpp → librats/storage/storage.cpp} +369 -522
- package/native-src/src/{storage.h → librats/storage/storage.h} +135 -299
- package/native-src/src/librats/subsystems/bittorrent.cpp +211 -0
- package/native-src/src/librats/subsystems/bittorrent.h +136 -0
- package/native-src/src/librats/subsystems/dht_discovery.cpp +202 -0
- package/native-src/src/librats/subsystems/dht_discovery.h +123 -0
- package/native-src/src/librats/subsystems/dht_service.h +36 -0
- package/native-src/src/librats/subsystems/file_transfer.cpp +972 -0
- package/native-src/src/librats/subsystems/file_transfer.h +367 -0
- package/native-src/src/librats/subsystems/hole_punch.cpp +605 -0
- package/native-src/src/librats/subsystems/hole_punch.h +290 -0
- package/native-src/src/librats/subsystems/hole_punch_service.h +38 -0
- package/native-src/src/librats/subsystems/mdns_discovery.cpp +66 -0
- package/native-src/src/librats/subsystems/mdns_discovery.h +55 -0
- package/native-src/src/librats/subsystems/message_json.cpp +112 -0
- package/native-src/src/librats/subsystems/message_json.h +88 -0
- package/native-src/src/librats/subsystems/peer_exchange.cpp +241 -0
- package/native-src/src/librats/subsystems/peer_exchange.h +136 -0
- package/native-src/src/librats/subsystems/ping_service.cpp +98 -0
- package/native-src/src/librats/subsystems/ping_service.h +66 -0
- package/native-src/src/librats/subsystems/port_mapping_service.cpp +192 -0
- package/native-src/src/librats/subsystems/port_mapping_service.h +84 -0
- package/native-src/src/librats/subsystems/pubsub.cpp +567 -0
- package/native-src/src/librats/subsystems/pubsub.h +175 -0
- package/native-src/src/librats/subsystems/reconnection.cpp +239 -0
- package/native-src/src/librats/subsystems/reconnection.h +126 -0
- package/native-src/src/librats/subsystems/relay.cpp +1142 -0
- package/native-src/src/librats/subsystems/relay.h +211 -0
- package/native-src/src/librats/subsystems/relay_service.h +46 -0
- package/native-src/src/librats/transport/connection.cpp +343 -0
- package/native-src/src/librats/transport/connection.h +283 -0
- package/native-src/src/librats/transport/link.h +96 -0
- package/native-src/src/librats/transport/reactor.cpp +588 -0
- package/native-src/src/librats/transport/reactor.h +262 -0
- package/native-src/src/librats/transport/reactor_pool.h +81 -0
- package/native-src/src/librats/transport/relay_link.cpp +208 -0
- package/native-src/src/librats/transport/relay_link.h +303 -0
- package/native-src/src/librats/transport/tcp_link.cpp +49 -0
- package/native-src/src/librats/transport/tcp_link.h +43 -0
- package/native-src/src/librats/transport/udp_mux.cpp +617 -0
- package/native-src/src/librats/transport/udp_mux.h +363 -0
- package/native-src/src/librats/transport/udp_packet.cpp +121 -0
- package/native-src/src/librats/transport/udp_packet.h +190 -0
- package/native-src/src/librats/transport/udp_stream.cpp +1194 -0
- package/native-src/src/librats/transport/udp_stream.h +614 -0
- package/native-src/src/librats/util/features.h.in +51 -0
- package/native-src/src/{fs.cpp → librats/util/fs.cpp} +51 -3
- package/native-src/src/librats/util/fs.h +136 -0
- package/native-src/src/librats/util/json.cpp +1002 -0
- package/native-src/src/librats/util/json.h +444 -0
- package/native-src/src/{logger.cpp → librats/util/logger.cpp} +1 -1
- package/native-src/src/{logger.h → librats/util/logger.h} +43 -31
- package/native-src/src/{network_monitor.cpp → librats/util/network_monitor.cpp} +12 -4
- package/native-src/src/{network_monitor.h → librats/util/network_monitor.h} +2 -1
- package/native-src/src/{network_utils.cpp → librats/util/network_utils.cpp} +38 -23
- package/native-src/src/{network_utils.h → librats/util/network_utils.h} +15 -8
- package/native-src/src/{os.cpp → librats/util/os.cpp} +48 -18
- package/native-src/src/librats/util/rats_export.h +69 -0
- package/native-src/src/{version.cpp → librats/util/version.cpp} +2 -2
- package/native-src/src/{version.h.in → librats/util/version.h.in} +1 -1
- package/native-src/src/librats/wire/frame.cpp +76 -0
- package/native-src/src/librats/wire/frame.h +111 -0
- package/native-src/src/librats/wire/message_router.cpp +45 -0
- package/native-src/src/librats/wire/message_router.h +47 -0
- package/package.json +5 -4
- package/scripts/build-librats.js +1 -0
- package/scripts/postinstall.js +3 -3
- package/scripts/prepare-package.js +4 -4
- package/scripts/verify-installation.js +63 -105
- package/src/librats_node.cpp +1067 -1323
- package/native-src/src/bencode.cpp +0 -485
- package/native-src/src/bencode.h +0 -145
- package/native-src/src/bittorrent.cpp +0 -14
- package/native-src/src/bittorrent.h +0 -74
- package/native-src/src/bt_bitfield.cpp +0 -372
- package/native-src/src/bt_bitfield.h +0 -316
- package/native-src/src/bt_choker.cpp +0 -228
- package/native-src/src/bt_choker.h +0 -147
- package/native-src/src/bt_client.cpp +0 -1047
- package/native-src/src/bt_client.h +0 -445
- package/native-src/src/bt_create_torrent.cpp +0 -677
- package/native-src/src/bt_create_torrent.h +0 -473
- package/native-src/src/bt_extension.cpp +0 -469
- package/native-src/src/bt_extension.h +0 -309
- package/native-src/src/bt_file_storage.cpp +0 -261
- package/native-src/src/bt_file_storage.h +0 -298
- package/native-src/src/bt_handshake.cpp +0 -134
- package/native-src/src/bt_handshake.h +0 -157
- package/native-src/src/bt_messages.cpp +0 -364
- package/native-src/src/bt_messages.h +0 -324
- package/native-src/src/bt_network.cpp +0 -1007
- package/native-src/src/bt_network.h +0 -417
- package/native-src/src/bt_peer_connection.cpp +0 -742
- package/native-src/src/bt_peer_connection.h +0 -592
- package/native-src/src/bt_piece_picker.cpp +0 -786
- package/native-src/src/bt_piece_picker.h +0 -473
- package/native-src/src/bt_resume_data.cpp +0 -410
- package/native-src/src/bt_resume_data.h +0 -249
- package/native-src/src/bt_torrent.cpp +0 -2120
- package/native-src/src/bt_torrent.h +0 -641
- package/native-src/src/bt_torrent_info.cpp +0 -659
- package/native-src/src/bt_torrent_info.h +0 -418
- package/native-src/src/bt_types.h +0 -621
- package/native-src/src/chained_send_buffer.cpp +0 -75
- package/native-src/src/chained_send_buffer.h +0 -137
- package/native-src/src/crypto/hkdf.c +0 -266
- package/native-src/src/crypto/poly1305.h +0 -36
- package/native-src/src/dht.cpp +0 -3311
- package/native-src/src/dht.h +0 -717
- package/native-src/src/disk_io.cpp +0 -632
- package/native-src/src/disk_io.h +0 -315
- package/native-src/src/file_transfer.cpp +0 -1415
- package/native-src/src/file_transfer.h +0 -286
- package/native-src/src/fs.h +0 -108
- package/native-src/src/gossipsub.cpp +0 -1139
- package/native-src/src/gossipsub.h +0 -403
- package/native-src/src/ice.cpp +0 -893
- package/native-src/src/ice.h +0 -559
- package/native-src/src/json.hpp +0 -25526
- package/native-src/src/librats.cpp +0 -2378
- package/native-src/src/librats.h +0 -2324
- package/native-src/src/librats_bittorrent.cpp +0 -601
- package/native-src/src/librats_c.cpp +0 -1557
- package/native-src/src/librats_c.h +0 -323
- package/native-src/src/librats_discovery.cpp +0 -402
- package/native-src/src/librats_encryption.cpp +0 -275
- package/native-src/src/librats_file_transfer.cpp +0 -144
- package/native-src/src/librats_gossipsub.cpp +0 -289
- package/native-src/src/librats_ice.cpp +0 -213
- package/native-src/src/librats_log_macros.h +0 -36
- package/native-src/src/librats_logging.cpp +0 -173
- package/native-src/src/librats_mdns.cpp +0 -166
- package/native-src/src/librats_persistence.cpp +0 -796
- package/native-src/src/librats_portmap.cpp +0 -419
- package/native-src/src/librats_reconnection.cpp +0 -218
- package/native-src/src/librats_statistic.cpp +0 -105
- package/native-src/src/librats_storage.cpp +0 -189
- package/native-src/src/rats_export.h +0 -17
- package/native-src/src/receive_buffer.cpp +0 -82
- package/native-src/src/receive_buffer.h +0 -127
- package/native-src/src/socket.h +0 -228
- package/native-src/src/threadmanager.cpp +0 -105
- package/native-src/src/threadmanager.h +0 -53
- package/native-src/src/tracker.cpp +0 -1264
- package/native-src/src/tracker.h +0 -319
- package/native-src/src/turn.cpp +0 -762
- package/native-src/src/turn.h +0 -460
- package/native-src/src/wakeup_pipe.h +0 -60
- /package/native-src/src/{os.h → librats/util/os.h} +0 -0
|
@@ -1,316 +0,0 @@
|
|
|
1
|
-
#pragma once
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @file bt_bitfield.h
|
|
5
|
-
* @brief Efficient bitfield implementation for piece tracking
|
|
6
|
-
*
|
|
7
|
-
* Provides a memory-efficient bitfield class for tracking which pieces
|
|
8
|
-
* have been downloaded or are available from peers.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
#include <vector>
|
|
12
|
-
#include <cstdint>
|
|
13
|
-
#include <cstddef>
|
|
14
|
-
#include <string>
|
|
15
|
-
|
|
16
|
-
namespace librats {
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @brief Efficient bit array for tracking pieces
|
|
20
|
-
*
|
|
21
|
-
* Uses packed uint32_t words for efficient memory usage and fast operations.
|
|
22
|
-
* Bits are stored in big-endian order within each byte to match BitTorrent
|
|
23
|
-
* protocol wire format.
|
|
24
|
-
*/
|
|
25
|
-
class Bitfield {
|
|
26
|
-
public:
|
|
27
|
-
/**
|
|
28
|
-
* @brief Default constructor - creates empty bitfield
|
|
29
|
-
*/
|
|
30
|
-
Bitfield() noexcept;
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* @brief Create bitfield with specified number of bits
|
|
34
|
-
* @param num_bits Number of bits in the bitfield
|
|
35
|
-
* @param initial_value Initial value for all bits (default: false)
|
|
36
|
-
*/
|
|
37
|
-
explicit Bitfield(size_t num_bits, bool initial_value = false);
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* @brief Copy constructor
|
|
41
|
-
*/
|
|
42
|
-
Bitfield(const Bitfield& other);
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* @brief Move constructor
|
|
46
|
-
*/
|
|
47
|
-
Bitfield(Bitfield&& other) noexcept;
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* @brief Copy assignment
|
|
51
|
-
*/
|
|
52
|
-
Bitfield& operator=(const Bitfield& other);
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* @brief Move assignment
|
|
56
|
-
*/
|
|
57
|
-
Bitfield& operator=(Bitfield&& other) noexcept;
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* @brief Destructor
|
|
61
|
-
*/
|
|
62
|
-
~Bitfield() = default;
|
|
63
|
-
|
|
64
|
-
//=========================================================================
|
|
65
|
-
// Bit Operations
|
|
66
|
-
//=========================================================================
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* @brief Set a bit to 1
|
|
70
|
-
* @param index Bit index (0-based)
|
|
71
|
-
*/
|
|
72
|
-
void set_bit(size_t index);
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* @brief Clear a bit to 0
|
|
76
|
-
* @param index Bit index (0-based)
|
|
77
|
-
*/
|
|
78
|
-
void clear_bit(size_t index);
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* @brief Get the value of a bit
|
|
82
|
-
* @param index Bit index (0-based)
|
|
83
|
-
* @return true if bit is set, false otherwise
|
|
84
|
-
*/
|
|
85
|
-
bool get_bit(size_t index) const;
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* @brief Operator[] for read access
|
|
89
|
-
* @param index Bit index
|
|
90
|
-
* @return true if bit is set
|
|
91
|
-
*/
|
|
92
|
-
bool operator[](size_t index) const { return get_bit(index); }
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* @brief Set all bits to 1
|
|
96
|
-
*/
|
|
97
|
-
void set_all();
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* @brief Clear all bits to 0
|
|
101
|
-
*/
|
|
102
|
-
void clear_all();
|
|
103
|
-
|
|
104
|
-
//=========================================================================
|
|
105
|
-
// Query Operations
|
|
106
|
-
//=========================================================================
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* @brief Check if all bits are set
|
|
110
|
-
* @return true if all bits are 1
|
|
111
|
-
*/
|
|
112
|
-
bool all_set() const;
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* @brief Check if no bits are set
|
|
116
|
-
* @return true if all bits are 0
|
|
117
|
-
*/
|
|
118
|
-
bool none_set() const;
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* @brief Count the number of set bits
|
|
122
|
-
* @return Number of bits that are 1
|
|
123
|
-
*/
|
|
124
|
-
size_t count() const;
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* @brief Get the total number of bits
|
|
128
|
-
* @return Size of the bitfield in bits
|
|
129
|
-
*/
|
|
130
|
-
size_t size() const noexcept { return num_bits_; }
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* @brief Check if bitfield is empty (size 0)
|
|
134
|
-
* @return true if no bits
|
|
135
|
-
*/
|
|
136
|
-
bool empty() const noexcept { return num_bits_ == 0; }
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* @brief Get number of bytes needed to store all bits
|
|
140
|
-
* @return Number of bytes
|
|
141
|
-
*/
|
|
142
|
-
size_t num_bytes() const noexcept { return (num_bits_ + 7) / 8; }
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* @brief Get number of 32-bit words used
|
|
146
|
-
* @return Number of uint32_t words
|
|
147
|
-
*/
|
|
148
|
-
size_t num_words() const noexcept { return data_.size(); }
|
|
149
|
-
|
|
150
|
-
//=========================================================================
|
|
151
|
-
// Bitwise Operations
|
|
152
|
-
//=========================================================================
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* @brief Bitwise AND with another bitfield
|
|
156
|
-
* @param other Other bitfield (must be same size)
|
|
157
|
-
* @return Reference to this bitfield
|
|
158
|
-
*/
|
|
159
|
-
Bitfield& operator&=(const Bitfield& other);
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* @brief Bitwise OR with another bitfield
|
|
163
|
-
* @param other Other bitfield (must be same size)
|
|
164
|
-
* @return Reference to this bitfield
|
|
165
|
-
*/
|
|
166
|
-
Bitfield& operator|=(const Bitfield& other);
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* @brief Bitwise XOR with another bitfield
|
|
170
|
-
* @param other Other bitfield (must be same size)
|
|
171
|
-
* @return Reference to this bitfield
|
|
172
|
-
*/
|
|
173
|
-
Bitfield& operator^=(const Bitfield& other);
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* @brief Bitwise NOT (complement)
|
|
177
|
-
* @return New bitfield with all bits flipped
|
|
178
|
-
*/
|
|
179
|
-
Bitfield operator~() const;
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* @brief Check if this bitfield has any bits that other doesn't have
|
|
183
|
-
* @param other Other bitfield
|
|
184
|
-
* @return true if (this & ~other) is non-zero
|
|
185
|
-
*/
|
|
186
|
-
bool has_bits_not_in(const Bitfield& other) const;
|
|
187
|
-
|
|
188
|
-
//=========================================================================
|
|
189
|
-
// Serialization (Wire Format)
|
|
190
|
-
//=========================================================================
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* @brief Convert to bytes for wire protocol
|
|
194
|
-
*
|
|
195
|
-
* Returns bytes in big-endian bit order as per BitTorrent spec.
|
|
196
|
-
* Trailing bits in last byte are set to 0.
|
|
197
|
-
*
|
|
198
|
-
* @return Vector of bytes
|
|
199
|
-
*/
|
|
200
|
-
std::vector<uint8_t> to_bytes() const;
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* @brief Create bitfield from bytes
|
|
204
|
-
*
|
|
205
|
-
* @param data Pointer to byte data
|
|
206
|
-
* @param data_len Length of data in bytes
|
|
207
|
-
* @param num_bits Number of bits (may be less than data_len * 8)
|
|
208
|
-
* @return New Bitfield
|
|
209
|
-
*/
|
|
210
|
-
static Bitfield from_bytes(const uint8_t* data, size_t data_len, size_t num_bits);
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* @brief Create bitfield from byte vector
|
|
214
|
-
*
|
|
215
|
-
* @param data Byte vector
|
|
216
|
-
* @param num_bits Number of bits
|
|
217
|
-
* @return New Bitfield
|
|
218
|
-
*/
|
|
219
|
-
static Bitfield from_bytes(const std::vector<uint8_t>& data, size_t num_bits);
|
|
220
|
-
|
|
221
|
-
//=========================================================================
|
|
222
|
-
// Resize
|
|
223
|
-
//=========================================================================
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* @brief Resize the bitfield
|
|
227
|
-
*
|
|
228
|
-
* @param new_size New number of bits
|
|
229
|
-
* @param value Value for new bits if growing
|
|
230
|
-
*/
|
|
231
|
-
void resize(size_t new_size, bool value = false);
|
|
232
|
-
|
|
233
|
-
//=========================================================================
|
|
234
|
-
// Iteration Helpers
|
|
235
|
-
//=========================================================================
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* @brief Find the first set bit
|
|
239
|
-
* @return Index of first set bit, or size() if none
|
|
240
|
-
*/
|
|
241
|
-
size_t find_first_set() const;
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
* @brief Find the first clear bit
|
|
245
|
-
* @return Index of first clear bit, or size() if none
|
|
246
|
-
*/
|
|
247
|
-
size_t find_first_clear() const;
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* @brief Find the next set bit after given index
|
|
251
|
-
* @param start Starting index (exclusive)
|
|
252
|
-
* @return Index of next set bit, or size() if none
|
|
253
|
-
*/
|
|
254
|
-
size_t find_next_set(size_t start) const;
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* @brief Find the next clear bit after given index
|
|
258
|
-
* @param start Starting index (exclusive)
|
|
259
|
-
* @return Index of next clear bit, or size() if none
|
|
260
|
-
*/
|
|
261
|
-
size_t find_next_clear(size_t start) const;
|
|
262
|
-
|
|
263
|
-
//=========================================================================
|
|
264
|
-
// Comparison
|
|
265
|
-
//=========================================================================
|
|
266
|
-
|
|
267
|
-
bool operator==(const Bitfield& other) const;
|
|
268
|
-
bool operator!=(const Bitfield& other) const { return !(*this == other); }
|
|
269
|
-
|
|
270
|
-
//=========================================================================
|
|
271
|
-
// Debug
|
|
272
|
-
//=========================================================================
|
|
273
|
-
|
|
274
|
-
/**
|
|
275
|
-
* @brief Convert to string representation for debugging
|
|
276
|
-
* @return String of '0' and '1' characters
|
|
277
|
-
*/
|
|
278
|
-
std::string to_string() const;
|
|
279
|
-
|
|
280
|
-
private:
|
|
281
|
-
std::vector<uint32_t> data_; ///< Packed bit storage
|
|
282
|
-
size_t num_bits_; ///< Total number of bits
|
|
283
|
-
|
|
284
|
-
/**
|
|
285
|
-
* @brief Clear trailing bits that are beyond num_bits_
|
|
286
|
-
*
|
|
287
|
-
* Called after operations that might set bits beyond the valid range
|
|
288
|
-
*/
|
|
289
|
-
void clear_trailing_bits();
|
|
290
|
-
|
|
291
|
-
/**
|
|
292
|
-
* @brief Count set bits in a 32-bit word (popcount)
|
|
293
|
-
*/
|
|
294
|
-
static size_t popcount32(uint32_t x);
|
|
295
|
-
};
|
|
296
|
-
|
|
297
|
-
//=============================================================================
|
|
298
|
-
// Free Functions
|
|
299
|
-
//=============================================================================
|
|
300
|
-
|
|
301
|
-
/**
|
|
302
|
-
* @brief Bitwise AND of two bitfields
|
|
303
|
-
*/
|
|
304
|
-
Bitfield operator&(const Bitfield& a, const Bitfield& b);
|
|
305
|
-
|
|
306
|
-
/**
|
|
307
|
-
* @brief Bitwise OR of two bitfields
|
|
308
|
-
*/
|
|
309
|
-
Bitfield operator|(const Bitfield& a, const Bitfield& b);
|
|
310
|
-
|
|
311
|
-
/**
|
|
312
|
-
* @brief Bitwise XOR of two bitfields
|
|
313
|
-
*/
|
|
314
|
-
Bitfield operator^(const Bitfield& a, const Bitfield& b);
|
|
315
|
-
|
|
316
|
-
} // namespace librats
|
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
#include "bt_choker.h"
|
|
2
|
-
#include "bt_peer_connection.h"
|
|
3
|
-
|
|
4
|
-
#include <algorithm>
|
|
5
|
-
#include <random>
|
|
6
|
-
|
|
7
|
-
namespace librats {
|
|
8
|
-
|
|
9
|
-
//=============================================================================
|
|
10
|
-
// Constructor
|
|
11
|
-
//=============================================================================
|
|
12
|
-
|
|
13
|
-
Choker::Choker()
|
|
14
|
-
: optimistic_peer_(nullptr)
|
|
15
|
-
, optimistic_rotation_index_(0) {
|
|
16
|
-
last_rechoke_ = std::chrono::steady_clock::now();
|
|
17
|
-
last_optimistic_rotation_ = std::chrono::steady_clock::now();
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
Choker::Choker(const ChokerConfig& config)
|
|
21
|
-
: config_(config)
|
|
22
|
-
, optimistic_peer_(nullptr)
|
|
23
|
-
, optimistic_rotation_index_(0) {
|
|
24
|
-
last_rechoke_ = std::chrono::steady_clock::now();
|
|
25
|
-
last_optimistic_rotation_ = std::chrono::steady_clock::now();
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
void Choker::set_config(const ChokerConfig& config) {
|
|
29
|
-
config_ = config;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
bool Choker::should_rechoke() const {
|
|
33
|
-
auto now = std::chrono::steady_clock::now();
|
|
34
|
-
return (now - last_rechoke_) >= config_.rechoke_interval;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
//=============================================================================
|
|
38
|
-
// Main Choking Algorithm
|
|
39
|
-
//=============================================================================
|
|
40
|
-
|
|
41
|
-
ChokeResult Choker::run(std::vector<ChokePeerInfo>& peers) {
|
|
42
|
-
last_rechoke_ = std::chrono::steady_clock::now();
|
|
43
|
-
|
|
44
|
-
if (config_.seed_mode) {
|
|
45
|
-
return run_seed_mode(peers);
|
|
46
|
-
} else {
|
|
47
|
-
return run_download_mode(peers);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
ChokeResult Choker::run_download_mode(std::vector<ChokePeerInfo>& peers) {
|
|
52
|
-
ChokeResult result;
|
|
53
|
-
|
|
54
|
-
if (peers.empty()) {
|
|
55
|
-
return result;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Check if we should rotate optimistic unchoke
|
|
59
|
-
auto now = std::chrono::steady_clock::now();
|
|
60
|
-
if ((now - last_optimistic_rotation_) >= config_.optimistic_interval) {
|
|
61
|
-
rotate_optimistic(peers);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Sort peers by download rate (best first)
|
|
65
|
-
// Only consider peers that are interested in us
|
|
66
|
-
std::vector<ChokePeerInfo*> interested_peers;
|
|
67
|
-
for (auto& peer : peers) {
|
|
68
|
-
if (peer.peer_interested && peer.connection != nullptr) {
|
|
69
|
-
interested_peers.push_back(&peer);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
std::sort(interested_peers.begin(), interested_peers.end(),
|
|
74
|
-
[](const ChokePeerInfo* a, const ChokePeerInfo* b) {
|
|
75
|
-
// Prefer peers with higher download rate to us
|
|
76
|
-
return a->download_rate > b->download_rate;
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
// Determine how many slots we have (excluding optimistic)
|
|
80
|
-
size_t regular_slots = config_.max_uploads;
|
|
81
|
-
if (optimistic_peer_ != nullptr) {
|
|
82
|
-
regular_slots = config_.max_uploads > 0 ? config_.max_uploads - 1 : 0;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Unchoke the top peers
|
|
86
|
-
size_t unchoked = 0;
|
|
87
|
-
for (auto* peer : interested_peers) {
|
|
88
|
-
if (peer->connection == optimistic_peer_) {
|
|
89
|
-
// Already counted as optimistic
|
|
90
|
-
if (peer->am_choking) {
|
|
91
|
-
result.to_unchoke.push_back(peer->connection);
|
|
92
|
-
peer->am_choking = false;
|
|
93
|
-
peer->last_unchoke = now;
|
|
94
|
-
}
|
|
95
|
-
continue;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
if (unchoked < regular_slots) {
|
|
99
|
-
if (peer->am_choking) {
|
|
100
|
-
result.to_unchoke.push_back(peer->connection);
|
|
101
|
-
peer->am_choking = false;
|
|
102
|
-
peer->last_unchoke = now;
|
|
103
|
-
}
|
|
104
|
-
++unchoked;
|
|
105
|
-
} else {
|
|
106
|
-
if (!peer->am_choking) {
|
|
107
|
-
result.to_choke.push_back(peer->connection);
|
|
108
|
-
peer->am_choking = true;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Choke peers who are no longer interested
|
|
114
|
-
for (auto& peer : peers) {
|
|
115
|
-
if (!peer.peer_interested && !peer.am_choking && peer.connection != nullptr) {
|
|
116
|
-
// Could optionally keep them unchoked for a bit
|
|
117
|
-
// For now, choke them
|
|
118
|
-
result.to_choke.push_back(peer.connection);
|
|
119
|
-
peer.am_choking = true;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
return result;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
ChokeResult Choker::run_seed_mode(std::vector<ChokePeerInfo>& peers) {
|
|
127
|
-
ChokeResult result;
|
|
128
|
-
|
|
129
|
-
if (peers.empty()) {
|
|
130
|
-
return result;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
auto now = std::chrono::steady_clock::now();
|
|
134
|
-
|
|
135
|
-
// In seed mode, we prioritize upload rate and round-robin fairness
|
|
136
|
-
// Sort by upload rate, but give some randomness
|
|
137
|
-
std::vector<ChokePeerInfo*> interested_peers;
|
|
138
|
-
for (auto& peer : peers) {
|
|
139
|
-
if (peer.peer_interested && peer.connection != nullptr) {
|
|
140
|
-
interested_peers.push_back(&peer);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Sort by upload rate (how fast we're uploading to them)
|
|
145
|
-
// and time since last unchoke for fairness
|
|
146
|
-
std::sort(interested_peers.begin(), interested_peers.end(),
|
|
147
|
-
[now](const ChokePeerInfo* a, const ChokePeerInfo* b) {
|
|
148
|
-
// Prioritize peers we haven't unchoked recently
|
|
149
|
-
auto a_time = std::chrono::duration_cast<std::chrono::seconds>(
|
|
150
|
-
now - a->last_unchoke).count();
|
|
151
|
-
auto b_time = std::chrono::duration_cast<std::chrono::seconds>(
|
|
152
|
-
now - b->last_unchoke).count();
|
|
153
|
-
|
|
154
|
-
// Mix of upload speed and fairness
|
|
155
|
-
double a_score = a->upload_rate + (a_time * 10.0);
|
|
156
|
-
double b_score = b->upload_rate + (b_time * 10.0);
|
|
157
|
-
|
|
158
|
-
return a_score > b_score;
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
// Unchoke top N
|
|
162
|
-
size_t unchoked = 0;
|
|
163
|
-
for (auto* peer : interested_peers) {
|
|
164
|
-
if (unchoked < config_.max_uploads) {
|
|
165
|
-
if (peer->am_choking) {
|
|
166
|
-
result.to_unchoke.push_back(peer->connection);
|
|
167
|
-
peer->am_choking = false;
|
|
168
|
-
peer->last_unchoke = now;
|
|
169
|
-
}
|
|
170
|
-
++unchoked;
|
|
171
|
-
} else {
|
|
172
|
-
if (!peer->am_choking) {
|
|
173
|
-
result.to_choke.push_back(peer->connection);
|
|
174
|
-
peer->am_choking = true;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
return result;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
void Choker::rotate_optimistic(std::vector<ChokePeerInfo>& peers) {
|
|
183
|
-
last_optimistic_rotation_ = std::chrono::steady_clock::now();
|
|
184
|
-
|
|
185
|
-
// Find peers that are currently choked and interested
|
|
186
|
-
std::vector<ChokePeerInfo*> candidates;
|
|
187
|
-
for (auto& peer : peers) {
|
|
188
|
-
if (peer.am_choking && peer.peer_interested && peer.connection != nullptr) {
|
|
189
|
-
candidates.push_back(&peer);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
if (candidates.empty()) {
|
|
194
|
-
optimistic_peer_ = nullptr;
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
// Prefer peers that have been connected for a short time (new peers)
|
|
199
|
-
// to give them a chance to prove themselves
|
|
200
|
-
std::sort(candidates.begin(), candidates.end(),
|
|
201
|
-
[](const ChokePeerInfo* a, const ChokePeerInfo* b) {
|
|
202
|
-
return a->connected_at > b->connected_at; // Newer first
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
// Pick with some randomness weighted towards newer peers
|
|
206
|
-
size_t index = 0;
|
|
207
|
-
if (candidates.size() > 1) {
|
|
208
|
-
// Prefer first 1/4 of candidates (newer)
|
|
209
|
-
size_t range = (std::max)(candidates.size() / 4, size_t(1));
|
|
210
|
-
|
|
211
|
-
static thread_local std::mt19937 gen(std::random_device{}());
|
|
212
|
-
std::uniform_int_distribution<size_t> dis(0, range - 1);
|
|
213
|
-
index = dis(gen);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
ChokePeerInfo* selected = candidates[index];
|
|
217
|
-
selected->is_optimistic = true;
|
|
218
|
-
optimistic_peer_ = selected->connection;
|
|
219
|
-
|
|
220
|
-
// Clear optimistic flag from previous peer
|
|
221
|
-
for (auto& peer : peers) {
|
|
222
|
-
if (peer.connection != optimistic_peer_) {
|
|
223
|
-
peer.is_optimistic = false;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
} // namespace librats
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
#pragma once
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @file bt_choker.h
|
|
5
|
-
* @brief BitTorrent choking algorithm
|
|
6
|
-
*
|
|
7
|
-
* Implements the tit-for-tat choking algorithm for fair bandwidth distribution.
|
|
8
|
-
* Includes optimistic unchoking for discovering faster peers.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
#include <vector>
|
|
12
|
-
#include <chrono>
|
|
13
|
-
#include <cstdint>
|
|
14
|
-
#include <functional>
|
|
15
|
-
|
|
16
|
-
namespace librats {
|
|
17
|
-
|
|
18
|
-
// Forward declaration
|
|
19
|
-
class BtPeerConnection;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @brief Configuration for the choking algorithm
|
|
23
|
-
*/
|
|
24
|
-
struct ChokerConfig {
|
|
25
|
-
size_t max_uploads; ///< Maximum unchoked peers (default: 4)
|
|
26
|
-
std::chrono::seconds rechoke_interval; ///< How often to re-evaluate (default: 10s)
|
|
27
|
-
std::chrono::seconds optimistic_interval;///< Optimistic unchoke rotation (default: 30s)
|
|
28
|
-
bool seed_mode; ///< Use seed choking algorithm
|
|
29
|
-
|
|
30
|
-
ChokerConfig()
|
|
31
|
-
: max_uploads(4)
|
|
32
|
-
, rechoke_interval(10)
|
|
33
|
-
, optimistic_interval(30)
|
|
34
|
-
, seed_mode(false) {}
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* @brief Peer info for choking decisions
|
|
39
|
-
*/
|
|
40
|
-
struct ChokePeerInfo {
|
|
41
|
-
BtPeerConnection* connection;
|
|
42
|
-
double download_rate; ///< Bytes/sec we're downloading from peer
|
|
43
|
-
double upload_rate; ///< Bytes/sec we're uploading to peer
|
|
44
|
-
bool am_choking; ///< Are we choking this peer?
|
|
45
|
-
bool am_interested; ///< Are we interested in this peer?
|
|
46
|
-
bool peer_interested; ///< Is peer interested in us?
|
|
47
|
-
bool is_optimistic; ///< Is this the optimistic unchoke slot?
|
|
48
|
-
bool is_snubbed; ///< Has peer not sent data recently?
|
|
49
|
-
|
|
50
|
-
std::chrono::steady_clock::time_point last_unchoke;
|
|
51
|
-
std::chrono::steady_clock::time_point connected_at;
|
|
52
|
-
|
|
53
|
-
ChokePeerInfo()
|
|
54
|
-
: connection(nullptr)
|
|
55
|
-
, download_rate(0), upload_rate(0)
|
|
56
|
-
, am_choking(true), am_interested(false), peer_interested(false)
|
|
57
|
-
, is_optimistic(false), is_snubbed(false) {}
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* @brief Result of a choking decision
|
|
62
|
-
*/
|
|
63
|
-
struct ChokeResult {
|
|
64
|
-
std::vector<BtPeerConnection*> to_choke; ///< Peers to choke
|
|
65
|
-
std::vector<BtPeerConnection*> to_unchoke; ///< Peers to unchoke
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* @brief Manages choking decisions for BitTorrent peers
|
|
70
|
-
*
|
|
71
|
-
* The choking algorithm ensures fair bandwidth distribution:
|
|
72
|
-
* - Unchoke top N peers based on download rate (reciprocation)
|
|
73
|
-
* - One optimistic unchoke slot rotates to discover new fast peers
|
|
74
|
-
* - Special handling for seed mode (upload-only)
|
|
75
|
-
*
|
|
76
|
-
* Thread-safe: Call run_choker() from a single thread.
|
|
77
|
-
*/
|
|
78
|
-
class Choker {
|
|
79
|
-
public:
|
|
80
|
-
/**
|
|
81
|
-
* @brief Create a choker with default config
|
|
82
|
-
*/
|
|
83
|
-
Choker();
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* @brief Create a choker with custom config
|
|
87
|
-
*/
|
|
88
|
-
explicit Choker(const ChokerConfig& config);
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* @brief Set configuration
|
|
92
|
-
*/
|
|
93
|
-
void set_config(const ChokerConfig& config);
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* @brief Get current configuration
|
|
97
|
-
*/
|
|
98
|
-
const ChokerConfig& config() const { return config_; }
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* @brief Set whether we're in seed mode
|
|
102
|
-
*/
|
|
103
|
-
void set_seed_mode(bool seed) { config_.seed_mode = seed; }
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* @brief Run the choking algorithm
|
|
107
|
-
*
|
|
108
|
-
* @param peers Current peer information
|
|
109
|
-
* @return Choking decisions
|
|
110
|
-
*/
|
|
111
|
-
ChokeResult run(std::vector<ChokePeerInfo>& peers);
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* @brief Check if it's time to rechoke
|
|
115
|
-
*/
|
|
116
|
-
bool should_rechoke() const;
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* @brief Get the optimistically unchoked peer
|
|
120
|
-
*/
|
|
121
|
-
BtPeerConnection* optimistic_peer() const { return optimistic_peer_; }
|
|
122
|
-
|
|
123
|
-
private:
|
|
124
|
-
/**
|
|
125
|
-
* @brief Run download mode choking (we're leeching)
|
|
126
|
-
*/
|
|
127
|
-
ChokeResult run_download_mode(std::vector<ChokePeerInfo>& peers);
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* @brief Run seed mode choking (we're seeding)
|
|
131
|
-
*/
|
|
132
|
-
ChokeResult run_seed_mode(std::vector<ChokePeerInfo>& peers);
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* @brief Select new optimistic unchoke peer
|
|
136
|
-
*/
|
|
137
|
-
void rotate_optimistic(std::vector<ChokePeerInfo>& peers);
|
|
138
|
-
|
|
139
|
-
ChokerConfig config_;
|
|
140
|
-
BtPeerConnection* optimistic_peer_;
|
|
141
|
-
|
|
142
|
-
std::chrono::steady_clock::time_point last_rechoke_;
|
|
143
|
-
std::chrono::steady_clock::time_point last_optimistic_rotation_;
|
|
144
|
-
size_t optimistic_rotation_index_;
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
} // namespace librats
|