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
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#include "librats/bittorrent/bitfield.h"
|
|
2
|
+
|
|
3
|
+
#include <algorithm>
|
|
4
|
+
#include <array>
|
|
5
|
+
|
|
6
|
+
namespace librats::bittorrent {
|
|
7
|
+
|
|
8
|
+
namespace {
|
|
9
|
+
|
|
10
|
+
/// 256-entry popcount table, built once. Reading a table beats per-bit work and
|
|
11
|
+
/// keeps count() branch-free and portable across compilers (no C++20 std::popcount).
|
|
12
|
+
const std::array<std::uint8_t, 256>& popcount_table() {
|
|
13
|
+
static const std::array<std::uint8_t, 256> table = [] {
|
|
14
|
+
std::array<std::uint8_t, 256> t{};
|
|
15
|
+
for (int i = 0; i < 256; ++i) {
|
|
16
|
+
std::uint8_t bits = 0;
|
|
17
|
+
for (int b = i; b; b >>= 1) bits += b & 1;
|
|
18
|
+
t[std::size_t(i)] = bits;
|
|
19
|
+
}
|
|
20
|
+
return t;
|
|
21
|
+
}();
|
|
22
|
+
return table;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
} // namespace
|
|
26
|
+
|
|
27
|
+
void Bitfield::resize(std::size_t bits, bool value) {
|
|
28
|
+
const std::size_t old_bits = bits_;
|
|
29
|
+
const std::size_t new_bytes = (bits + 7) / 8;
|
|
30
|
+
|
|
31
|
+
// resize() fills only the *newly appended* bytes with the fill value.
|
|
32
|
+
bytes_.resize(new_bytes, value ? 0xFFu : 0x00u);
|
|
33
|
+
bits_ = bits;
|
|
34
|
+
|
|
35
|
+
// When growing with value=true, the spare bits left over in the old (partial)
|
|
36
|
+
// last byte were trailing zeros and weren't touched by resize() — set them.
|
|
37
|
+
if (value && bits > old_bits) {
|
|
38
|
+
const std::size_t old_byte_end = (old_bits + 7) / 8 * 8; // bit just past old last byte
|
|
39
|
+
for (std::size_t i = old_bits; i < (std::min)(bits, old_byte_end); ++i) set(i);
|
|
40
|
+
}
|
|
41
|
+
clear_trailing_bits();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
void Bitfield::assign(const std::uint8_t* data, std::size_t bytes, std::size_t bits) {
|
|
45
|
+
bytes_.assign(data, data + bytes);
|
|
46
|
+
bytes_.resize((bits + 7) / 8, 0x00u); // tolerate a short/long wire buffer
|
|
47
|
+
bits_ = bits;
|
|
48
|
+
clear_trailing_bits();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
void Bitfield::clear_trailing_bits() noexcept {
|
|
52
|
+
const std::size_t rem = bits_ & 7;
|
|
53
|
+
if (rem != 0 && !bytes_.empty()) {
|
|
54
|
+
bytes_.back() &= std::uint8_t(0xFFu << (8 - rem)); // keep the top `rem` bits
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
std::size_t Bitfield::count() const noexcept {
|
|
59
|
+
// Spare bits are always zero, so whole-byte popcount is exact.
|
|
60
|
+
const auto& tbl = popcount_table();
|
|
61
|
+
std::size_t n = 0;
|
|
62
|
+
for (std::uint8_t b : bytes_) n += tbl[b];
|
|
63
|
+
return n;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
bool Bitfield::all_set() const noexcept {
|
|
67
|
+
return find_first_unset() == bits_;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
bool Bitfield::none_set() const noexcept {
|
|
71
|
+
for (std::uint8_t b : bytes_) if (b != 0) return false;
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
void Bitfield::set_all() noexcept {
|
|
76
|
+
std::fill(bytes_.begin(), bytes_.end(), 0xFFu);
|
|
77
|
+
clear_trailing_bits();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
void Bitfield::clear_all() noexcept {
|
|
81
|
+
std::fill(bytes_.begin(), bytes_.end(), 0x00u);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
std::size_t Bitfield::find_first_unset() const noexcept {
|
|
85
|
+
for (std::size_t bi = 0; bi < bytes_.size(); ++bi) {
|
|
86
|
+
if (bytes_[bi] == 0xFFu) continue; // fully set byte — skip fast
|
|
87
|
+
const std::size_t base = bi * 8;
|
|
88
|
+
for (std::size_t k = 0; k < 8; ++k) {
|
|
89
|
+
const std::size_t idx = base + k;
|
|
90
|
+
if (idx >= bits_) return bits_;
|
|
91
|
+
if (!get(idx)) return idx;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return bits_;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
} // namespace librats::bittorrent
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file bitfield.h
|
|
5
|
+
* @brief A compact, wire-compatible bit set — the BitTorrent "bitfield".
|
|
6
|
+
*
|
|
7
|
+
* Bits are packed MSB-first within each byte (bit @c i lives in byte @c i/8 at
|
|
8
|
+
* mask @c 0x80>>(i%8)), which is exactly the on-wire layout of the BEP 3
|
|
9
|
+
* `bitfield` message. So data()/data_size() can be sent verbatim and assign()
|
|
10
|
+
* ingests a received message with no conversion. Spare bits in the final byte
|
|
11
|
+
* are always kept zero, which lets count()/none_set() scan whole bytes safely.
|
|
12
|
+
*
|
|
13
|
+
* Owned by a single torrent on the network thread — deliberately not thread-safe.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
#include "librats/util/rats_export.h"
|
|
17
|
+
|
|
18
|
+
#include <cstddef>
|
|
19
|
+
#include <cstdint>
|
|
20
|
+
#include <vector>
|
|
21
|
+
|
|
22
|
+
namespace librats::bittorrent {
|
|
23
|
+
|
|
24
|
+
class RATS_API Bitfield {
|
|
25
|
+
public:
|
|
26
|
+
Bitfield() = default;
|
|
27
|
+
explicit Bitfield(std::size_t bits, bool value = false) { resize(bits, value); }
|
|
28
|
+
|
|
29
|
+
/// Resize to @p bits bits; any newly added bits take @p value. Existing bits preserved.
|
|
30
|
+
void resize(std::size_t bits, bool value = false);
|
|
31
|
+
|
|
32
|
+
/// Ingest a received wire bitfield: @p bytes raw bytes interpreted as @p bits bits.
|
|
33
|
+
/// Spare bits beyond @p bits are cleared so the invariant holds.
|
|
34
|
+
void assign(const std::uint8_t* data, std::size_t bytes, std::size_t bits);
|
|
35
|
+
|
|
36
|
+
void clear() noexcept { bytes_.clear(); bits_ = 0; }
|
|
37
|
+
|
|
38
|
+
std::size_t size() const noexcept { return bits_; }
|
|
39
|
+
std::size_t num_bytes() const noexcept { return bytes_.size(); }
|
|
40
|
+
bool empty() const noexcept { return bits_ == 0; }
|
|
41
|
+
|
|
42
|
+
bool get(std::size_t i) const noexcept {
|
|
43
|
+
return (bytes_[i >> 3] & (0x80u >> (i & 7))) != 0;
|
|
44
|
+
}
|
|
45
|
+
bool operator[](std::size_t i) const noexcept { return get(i); }
|
|
46
|
+
|
|
47
|
+
void set(std::size_t i) noexcept { bytes_[i >> 3] |= std::uint8_t(0x80u >> (i & 7)); }
|
|
48
|
+
void reset(std::size_t i) noexcept { bytes_[i >> 3] &= std::uint8_t(~(0x80u >> (i & 7))); }
|
|
49
|
+
void set(std::size_t i, bool v) noexcept { if (v) set(i); else reset(i); }
|
|
50
|
+
|
|
51
|
+
std::size_t count() const noexcept; ///< number of set bits
|
|
52
|
+
bool all_set() const noexcept;
|
|
53
|
+
bool none_set() const noexcept;
|
|
54
|
+
void set_all() noexcept;
|
|
55
|
+
void clear_all() noexcept;
|
|
56
|
+
|
|
57
|
+
/// First index whose bit is 0, or size() if all bits are set. Answers
|
|
58
|
+
/// "what is the first piece I still need?".
|
|
59
|
+
std::size_t find_first_unset() const noexcept;
|
|
60
|
+
|
|
61
|
+
const std::uint8_t* data() const noexcept { return bytes_.data(); }
|
|
62
|
+
std::size_t data_size() const noexcept { return bytes_.size(); }
|
|
63
|
+
|
|
64
|
+
bool operator==(const Bitfield& o) const noexcept {
|
|
65
|
+
return bits_ == o.bits_ && bytes_ == o.bytes_;
|
|
66
|
+
}
|
|
67
|
+
bool operator!=(const Bitfield& o) const noexcept { return !(*this == o); }
|
|
68
|
+
|
|
69
|
+
private:
|
|
70
|
+
void clear_trailing_bits() noexcept; ///< keep the spare bits of the last byte zero
|
|
71
|
+
|
|
72
|
+
std::vector<std::uint8_t> bytes_;
|
|
73
|
+
std::size_t bits_ = 0;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
} // namespace librats::bittorrent
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file byte_io.h
|
|
5
|
+
* @brief Big-endian (network order) integer read/write helpers for the BitTorrent wire.
|
|
6
|
+
*
|
|
7
|
+
* The BitTorrent peer protocol, the BEP 15 UDP tracker protocol and extension
|
|
8
|
+
* messages are all big-endian. These tiny inline helpers keep (de)serialisation
|
|
9
|
+
* obvious and endianness-correct, without sprinkling htonl/ntohl or manual shifts
|
|
10
|
+
* across the codebase.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
#include "librats/core/bytes.h"
|
|
14
|
+
|
|
15
|
+
#include <cstddef>
|
|
16
|
+
#include <cstdint>
|
|
17
|
+
|
|
18
|
+
namespace librats::bittorrent {
|
|
19
|
+
|
|
20
|
+
inline std::uint16_t read_u16_be(const std::uint8_t* p) noexcept {
|
|
21
|
+
return std::uint16_t(std::uint16_t(p[0]) << 8 | std::uint16_t(p[1]));
|
|
22
|
+
}
|
|
23
|
+
inline std::uint32_t read_u32_be(const std::uint8_t* p) noexcept {
|
|
24
|
+
return std::uint32_t(p[0]) << 24 | std::uint32_t(p[1]) << 16
|
|
25
|
+
| std::uint32_t(p[2]) << 8 | std::uint32_t(p[3]);
|
|
26
|
+
}
|
|
27
|
+
inline std::uint64_t read_u64_be(const std::uint8_t* p) noexcept {
|
|
28
|
+
return std::uint64_t(read_u32_be(p)) << 32 | read_u32_be(p + 4);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
inline void write_u16_be(std::uint8_t* p, std::uint16_t v) noexcept {
|
|
32
|
+
p[0] = std::uint8_t(v >> 8);
|
|
33
|
+
p[1] = std::uint8_t(v);
|
|
34
|
+
}
|
|
35
|
+
inline void write_u32_be(std::uint8_t* p, std::uint32_t v) noexcept {
|
|
36
|
+
p[0] = std::uint8_t(v >> 24);
|
|
37
|
+
p[1] = std::uint8_t(v >> 16);
|
|
38
|
+
p[2] = std::uint8_t(v >> 8);
|
|
39
|
+
p[3] = std::uint8_t(v);
|
|
40
|
+
}
|
|
41
|
+
inline void write_u64_be(std::uint8_t* p, std::uint64_t v) noexcept {
|
|
42
|
+
write_u32_be(p, std::uint32_t(v >> 32));
|
|
43
|
+
write_u32_be(p + 4, std::uint32_t(v));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Append helpers — grow a Bytes buffer with one big-endian value.
|
|
47
|
+
inline void append_u8(Bytes& b, std::uint8_t v) { b.push_back(v); }
|
|
48
|
+
inline void append_u16_be(Bytes& b, std::uint16_t v) {
|
|
49
|
+
std::uint8_t t[2]; write_u16_be(t, v); b.insert(b.end(), t, t + 2);
|
|
50
|
+
}
|
|
51
|
+
inline void append_u32_be(Bytes& b, std::uint32_t v) {
|
|
52
|
+
std::uint8_t t[4]; write_u32_be(t, v); b.insert(b.end(), t, t + 4);
|
|
53
|
+
}
|
|
54
|
+
inline void append_u64_be(Bytes& b, std::uint64_t v) {
|
|
55
|
+
std::uint8_t t[8]; write_u64_be(t, v); b.insert(b.end(), t, t + 8);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
} // namespace librats::bittorrent
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#include "librats/bittorrent/choker.h"
|
|
2
|
+
|
|
3
|
+
#include <algorithm>
|
|
4
|
+
|
|
5
|
+
namespace librats::bittorrent {
|
|
6
|
+
|
|
7
|
+
std::vector<const void*> Choker::select(std::vector<Candidate> candidates,
|
|
8
|
+
const void* optimistic) const {
|
|
9
|
+
// Highest score first; stable so equal-score peers keep a deterministic order.
|
|
10
|
+
std::stable_sort(candidates.begin(), candidates.end(),
|
|
11
|
+
[](const Candidate& a, const Candidate& b) { return a.score > b.score; });
|
|
12
|
+
|
|
13
|
+
std::vector<const void*> chosen;
|
|
14
|
+
const std::size_t take = (std::min)(slots_, candidates.size());
|
|
15
|
+
chosen.reserve(take + 1);
|
|
16
|
+
for (std::size_t i = 0; i < take; ++i) chosen.push_back(candidates[i].peer);
|
|
17
|
+
|
|
18
|
+
if (optimistic &&
|
|
19
|
+
std::find(chosen.begin(), chosen.end(), optimistic) == chosen.end()) {
|
|
20
|
+
chosen.push_back(optimistic);
|
|
21
|
+
}
|
|
22
|
+
return chosen;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
} // namespace librats::bittorrent
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file choker.h
|
|
5
|
+
* @brief The unchoke decision — who we upload to.
|
|
6
|
+
*
|
|
7
|
+
* BitTorrent reciprocates: a leecher unchokes the peers that feed it fastest
|
|
8
|
+
* (tit-for-tat), a seed spreads its slots by upload rate. The Choker is a pure
|
|
9
|
+
* policy over a list of *interested* candidates scored by the caller (recent
|
|
10
|
+
* bytes received from them, or served to them when seeding): it returns the
|
|
11
|
+
* subset to unchoke — the top `slots` by score, plus an optional optimistic
|
|
12
|
+
* unchoke that gets a chance regardless of score so newcomers can bootstrap.
|
|
13
|
+
*
|
|
14
|
+
* Stateless and side-effect-free, so the Torrent can recompute it each round and
|
|
15
|
+
* apply the diff against current choke state.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#include <cstddef>
|
|
19
|
+
#include <cstdint>
|
|
20
|
+
#include <vector>
|
|
21
|
+
|
|
22
|
+
namespace librats::bittorrent {
|
|
23
|
+
|
|
24
|
+
class Choker {
|
|
25
|
+
public:
|
|
26
|
+
explicit Choker(std::size_t upload_slots = 4) : slots_(upload_slots) {}
|
|
27
|
+
|
|
28
|
+
void set_slots(std::size_t slots) noexcept { slots_ = slots; }
|
|
29
|
+
std::size_t slots() const noexcept { return slots_; }
|
|
30
|
+
|
|
31
|
+
struct Candidate {
|
|
32
|
+
const void* peer = nullptr; ///< opaque peer identity
|
|
33
|
+
std::uint64_t score = 0; ///< higher = more deserving of a slot
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/// Choose who to unchoke. Pass only *interested* peers. The result holds the
|
|
37
|
+
/// top `slots` by score; if @p optimistic is non-null it is always included
|
|
38
|
+
/// (an extra slot if it didn't already make the cut).
|
|
39
|
+
std::vector<const void*> select(std::vector<Candidate> candidates,
|
|
40
|
+
const void* optimistic = nullptr) const;
|
|
41
|
+
|
|
42
|
+
private:
|
|
43
|
+
std::size_t slots_;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
} // namespace librats::bittorrent
|