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,194 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file peer_connection.h
|
|
5
|
+
* @brief One peer link: the BitTorrent wire handshake, message codec and the
|
|
6
|
+
* choke/interest state machine.
|
|
7
|
+
*
|
|
8
|
+
* A PeerConnection owns a non-blocking TCP socket registered with a Reactor and
|
|
9
|
+
* lives entirely on that reactor's thread. It turns the byte stream into
|
|
10
|
+
* protocol events delivered to an Observer, and offers send_* methods to emit
|
|
11
|
+
* messages. It deliberately knows nothing about pieces-to-request strategy or
|
|
12
|
+
* disk — the owning Torrent (a later phase) drives those through this surface.
|
|
13
|
+
*
|
|
14
|
+
* Wire format: a 68-byte handshake, then length-prefixed messages
|
|
15
|
+
* `[u32 length][u8 id][payload]` (length 0 = keep-alive). All integers are
|
|
16
|
+
* big-endian.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
#include "librats/bittorrent/bitfield.h"
|
|
20
|
+
#include "librats/bittorrent/reactor.h"
|
|
21
|
+
#include "librats/bittorrent/types.h"
|
|
22
|
+
#include "librats/core/bytes.h"
|
|
23
|
+
#include "librats/core/chained_send_buffer.h"
|
|
24
|
+
#include "librats/core/receive_buffer.h"
|
|
25
|
+
|
|
26
|
+
#include <chrono>
|
|
27
|
+
#include <cstdint>
|
|
28
|
+
#include <functional>
|
|
29
|
+
#include <string>
|
|
30
|
+
#include <vector>
|
|
31
|
+
|
|
32
|
+
namespace librats::bittorrent {
|
|
33
|
+
|
|
34
|
+
enum class MessageId : std::uint8_t {
|
|
35
|
+
Choke = 0,
|
|
36
|
+
Unchoke = 1,
|
|
37
|
+
Interested = 2,
|
|
38
|
+
NotInterested = 3,
|
|
39
|
+
Have = 4,
|
|
40
|
+
Bitfield = 5,
|
|
41
|
+
Request = 6,
|
|
42
|
+
Piece = 7,
|
|
43
|
+
Cancel = 8,
|
|
44
|
+
Port = 9,
|
|
45
|
+
Extended = 20,
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
class PeerConnection {
|
|
49
|
+
public:
|
|
50
|
+
/// Protocol events. All fire on the reactor thread; ByteView arguments are
|
|
51
|
+
/// only valid for the duration of the call (copy if you need to keep them).
|
|
52
|
+
struct Observer {
|
|
53
|
+
virtual ~Observer() = default;
|
|
54
|
+
virtual void on_handshake(PeerConnection&, const InfoHash&, const PeerId&) {}
|
|
55
|
+
virtual void on_choke(PeerConnection&, bool peer_choking) {}
|
|
56
|
+
virtual void on_interest(PeerConnection&, bool peer_interested) {}
|
|
57
|
+
virtual void on_have(PeerConnection&, std::uint32_t piece) {}
|
|
58
|
+
virtual void on_bitfield(PeerConnection&, const Bitfield&) {}
|
|
59
|
+
virtual void on_request(PeerConnection&, std::uint32_t piece, std::uint32_t offset, std::uint32_t length) {}
|
|
60
|
+
virtual void on_piece(PeerConnection&, std::uint32_t piece, std::uint32_t offset, ByteView data) {}
|
|
61
|
+
virtual void on_cancel(PeerConnection&, std::uint32_t piece, std::uint32_t offset, std::uint32_t length) {}
|
|
62
|
+
virtual void on_port(PeerConnection&, std::uint16_t port) {}
|
|
63
|
+
virtual void on_extended(PeerConnection&, std::uint8_t ext_id, ByteView payload) {}
|
|
64
|
+
virtual void on_closed(PeerConnection&, const std::string& reason) {}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/// Late-binding info for an incoming connection: filled by the Resolver once
|
|
68
|
+
/// the peer's handshake reveals which torrent it is for.
|
|
69
|
+
struct Binding {
|
|
70
|
+
Observer* observer = nullptr;
|
|
71
|
+
std::uint32_t num_pieces = 0;
|
|
72
|
+
};
|
|
73
|
+
/// Maps an incoming handshake's info-hash to a torrent. Return false to reject.
|
|
74
|
+
using Resolver = std::function<bool(const InfoHash& their_info_hash, Binding& out)>;
|
|
75
|
+
|
|
76
|
+
/// Outgoing connection: we know the torrent up front.
|
|
77
|
+
/// @param num_pieces sizes the peer's bitfield; 0 if metadata isn't known yet.
|
|
78
|
+
PeerConnection(Reactor& reactor, socket_t sock, bool outgoing,
|
|
79
|
+
const InfoHash& info_hash, const PeerId& our_peer_id,
|
|
80
|
+
std::uint32_t num_pieces, Observer* observer,
|
|
81
|
+
std::string remote_ip = "", std::uint16_t remote_port = 0);
|
|
82
|
+
/// Incoming connection: the torrent is resolved from the peer's handshake.
|
|
83
|
+
PeerConnection(Reactor& reactor, socket_t sock, const PeerId& our_peer_id,
|
|
84
|
+
Resolver resolver, std::string remote_ip = "", std::uint16_t remote_port = 0);
|
|
85
|
+
~PeerConnection();
|
|
86
|
+
|
|
87
|
+
PeerConnection(const PeerConnection&) = delete;
|
|
88
|
+
PeerConnection& operator=(const PeerConnection&) = delete;
|
|
89
|
+
|
|
90
|
+
/// Register with the reactor; an outgoing connection sends its handshake now.
|
|
91
|
+
void start();
|
|
92
|
+
/// Tear down: deregister, close the socket, fire on_closed once.
|
|
93
|
+
void close(const std::string& reason);
|
|
94
|
+
|
|
95
|
+
// ---- state ----
|
|
96
|
+
bool closed() const noexcept { return closed_; }
|
|
97
|
+
bool handshake_done() const noexcept { return handshake_sent_ && handshake_received_; }
|
|
98
|
+
bool outgoing() const noexcept { return outgoing_; }
|
|
99
|
+
bool am_choking() const noexcept { return am_choking_; }
|
|
100
|
+
bool am_interested() const noexcept { return am_interested_; }
|
|
101
|
+
bool peer_choking() const noexcept { return peer_choking_; }
|
|
102
|
+
bool peer_interested() const noexcept { return peer_interested_; }
|
|
103
|
+
const Bitfield& peer_bitfield() const noexcept { return peer_have_; }
|
|
104
|
+
const PeerId& peer_id() const noexcept { return peer_id_; }
|
|
105
|
+
const InfoHash& info_hash() const noexcept { return info_hash_; }
|
|
106
|
+
bool peer_supports_extensions() const noexcept { return reserved::has_extensions(peer_reserved_); }
|
|
107
|
+
const std::string& remote_ip() const noexcept { return remote_ip_; }
|
|
108
|
+
std::uint16_t remote_port() const noexcept { return remote_port_; }
|
|
109
|
+
|
|
110
|
+
// ---- send ----
|
|
111
|
+
void send_keepalive();
|
|
112
|
+
void send_choke();
|
|
113
|
+
void send_unchoke();
|
|
114
|
+
void send_interested();
|
|
115
|
+
void send_not_interested();
|
|
116
|
+
void send_have(std::uint32_t piece);
|
|
117
|
+
void send_bitfield(const Bitfield& bitfield);
|
|
118
|
+
void send_request(std::uint32_t piece, std::uint32_t offset, std::uint32_t length);
|
|
119
|
+
/// Takes ownership of `data` — the block goes into the send queue as its own
|
|
120
|
+
/// chunk, so a disk read is handed straight to the socket without a copy.
|
|
121
|
+
void send_piece(std::uint32_t piece, std::uint32_t offset, Bytes data);
|
|
122
|
+
void send_cancel(std::uint32_t piece, std::uint32_t offset, std::uint32_t length);
|
|
123
|
+
void send_port(std::uint16_t port);
|
|
124
|
+
void send_extended(std::uint8_t ext_id, ByteView payload);
|
|
125
|
+
|
|
126
|
+
private:
|
|
127
|
+
void on_io(std::uint32_t events);
|
|
128
|
+
void do_read();
|
|
129
|
+
std::size_t read_size() const; ///< bytes to offer the next recv() (see rx_need_)
|
|
130
|
+
void parse();
|
|
131
|
+
bool parse_handshake();
|
|
132
|
+
void send_handshake();
|
|
133
|
+
void dispatch(MessageId id, const std::uint8_t* payload, std::uint32_t len);
|
|
134
|
+
|
|
135
|
+
void send_message(MessageId id, const std::uint8_t* payload, std::uint32_t len);
|
|
136
|
+
/// Append to the send queue. No syscall: the caller flushes once the whole
|
|
137
|
+
/// message is queued, so a message never costs more than one send().
|
|
138
|
+
void queue(ByteView bytes) { if (!closed_) tx_.append(bytes); }
|
|
139
|
+
/// Queue a buffer the caller already owns — moved in, never copied.
|
|
140
|
+
void queue(Bytes bytes) { if (!closed_) tx_.append(std::move(bytes)); }
|
|
141
|
+
/// Push the queue to the socket with one gather-send, (dis)arm write interest,
|
|
142
|
+
/// and enforce the send high-water mark. May close the connection.
|
|
143
|
+
void flush();
|
|
144
|
+
void want_write(bool on);
|
|
145
|
+
/// Periodic self-rescheduling tick: enforces the handshake/idle deadlines and
|
|
146
|
+
/// emits keep-alives. Stops rescheduling once the connection is closed.
|
|
147
|
+
void tick();
|
|
148
|
+
|
|
149
|
+
Reactor& reactor_;
|
|
150
|
+
socket_t sock_;
|
|
151
|
+
bool outgoing_;
|
|
152
|
+
InfoHash info_hash_;
|
|
153
|
+
PeerId our_peer_id_;
|
|
154
|
+
PeerId peer_id_{};
|
|
155
|
+
std::uint32_t num_pieces_;
|
|
156
|
+
Observer* obs_;
|
|
157
|
+
Resolver resolver_; ///< incoming only; resolves the torrent
|
|
158
|
+
bool bound_ = true; ///< false for an unresolved incoming connection
|
|
159
|
+
std::string remote_ip_; ///< peer's address (source for incoming, dialed for outgoing)
|
|
160
|
+
std::uint16_t remote_port_ = 0;
|
|
161
|
+
|
|
162
|
+
ReceiveBuffer rx_;
|
|
163
|
+
/// Wire size of the message rx_ is mid-way through (4-byte prefix included), once
|
|
164
|
+
/// that prefix has been read; 0 when no message is in flight. Lets the next recv()
|
|
165
|
+
/// size rx_ for the whole message in one go. Peer-declared, hence capped.
|
|
166
|
+
std::size_t rx_need_ = 0;
|
|
167
|
+
ChainedSendBuffer tx_;
|
|
168
|
+
bool want_write_ = false;
|
|
169
|
+
|
|
170
|
+
// Timeout bookkeeping, all evaluated by the periodic tick().
|
|
171
|
+
TimerId tick_timer_ = kInvalidTimerId;
|
|
172
|
+
std::chrono::steady_clock::time_point created_{}; ///< start() time — handshake deadline
|
|
173
|
+
std::chrono::steady_clock::time_point last_recv_{}; ///< last byte received — idle deadline
|
|
174
|
+
std::chrono::steady_clock::time_point last_sent_{}; ///< last byte sent — keep-alive timer
|
|
175
|
+
|
|
176
|
+
bool started_ = false;
|
|
177
|
+
bool handshake_sent_ = false;
|
|
178
|
+
bool handshake_received_= false;
|
|
179
|
+
bool closed_ = false;
|
|
180
|
+
|
|
181
|
+
bool am_choking_ = true;
|
|
182
|
+
bool am_interested_ = false;
|
|
183
|
+
bool peer_choking_ = true;
|
|
184
|
+
bool peer_interested_ = false;
|
|
185
|
+
/// A bitfield is only valid as the peer's first piece-state message (BEP 3).
|
|
186
|
+
/// Set once the peer has sent a bitfield or any HAVE; a later bitfield is then
|
|
187
|
+
/// rejected so we can't double-count its availability against a single per-bit
|
|
188
|
+
/// decrement at disconnect.
|
|
189
|
+
bool piece_state_begun_ = false;
|
|
190
|
+
Bitfield peer_have_;
|
|
191
|
+
ReservedBytes peer_reserved_{};
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
} // namespace librats::bittorrent
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#include "librats/bittorrent/peer_list.h"
|
|
2
|
+
|
|
3
|
+
#include <algorithm>
|
|
4
|
+
|
|
5
|
+
namespace librats::bittorrent {
|
|
6
|
+
|
|
7
|
+
bool PeerList::add(const std::string& ip, std::uint16_t port, PeerSource source) {
|
|
8
|
+
if (ip.empty() || port == 0) return false;
|
|
9
|
+
auto [it, inserted] = peers_.try_emplace(key(ip, port));
|
|
10
|
+
Peer& p = it->second;
|
|
11
|
+
p.sources |= std::uint8_t(source);
|
|
12
|
+
if (inserted) { p.ip = ip; p.port = port; }
|
|
13
|
+
return inserted;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
std::vector<PeerList::Endpoint> PeerList::connect_candidates(std::size_t max) {
|
|
17
|
+
std::vector<Peer*> eligible_peers;
|
|
18
|
+
for (auto& [k, p] : peers_)
|
|
19
|
+
if (eligible(p)) eligible_peers.push_back(&p);
|
|
20
|
+
|
|
21
|
+
// Fewest past failures first; ties broken by richer source provenance so a
|
|
22
|
+
// tracker/DHT-vouched peer outranks one only seen via PEX.
|
|
23
|
+
std::sort(eligible_peers.begin(), eligible_peers.end(), [](const Peer* a, const Peer* b) {
|
|
24
|
+
if (a->fail_count != b->fail_count) return a->fail_count < b->fail_count;
|
|
25
|
+
return a->sources > b->sources;
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
std::vector<Endpoint> out;
|
|
29
|
+
const std::size_t take = (std::min)(max, eligible_peers.size());
|
|
30
|
+
out.reserve(take);
|
|
31
|
+
for (std::size_t i = 0; i < take; ++i) {
|
|
32
|
+
eligible_peers[i]->connecting = true;
|
|
33
|
+
out.push_back(Endpoint{eligible_peers[i]->ip, eligible_peers[i]->port});
|
|
34
|
+
}
|
|
35
|
+
return out;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
void PeerList::set_connected(const std::string& ip, std::uint16_t port, bool connected) {
|
|
39
|
+
auto it = peers_.find(key(ip, port));
|
|
40
|
+
if (it == peers_.end()) return;
|
|
41
|
+
it->second.connected = connected;
|
|
42
|
+
it->second.connecting = false;
|
|
43
|
+
if (connected) it->second.fail_count = 0; // a successful connect clears the penalty
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
void PeerList::on_connect_failed(const std::string& ip, std::uint16_t port) {
|
|
47
|
+
auto it = peers_.find(key(ip, port));
|
|
48
|
+
if (it == peers_.end()) return;
|
|
49
|
+
it->second.connecting = false;
|
|
50
|
+
++it->second.fail_count;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
void PeerList::ban(const std::string& ip, std::uint16_t port) {
|
|
54
|
+
auto it = peers_.find(key(ip, port));
|
|
55
|
+
if (it != peers_.end()) it->second.banned = true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
std::size_t PeerList::num_candidates() const {
|
|
59
|
+
std::size_t n = 0;
|
|
60
|
+
for (const auto& [k, p] : peers_) if (eligible(p)) ++n;
|
|
61
|
+
return n;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
bool PeerList::contains(const std::string& ip, std::uint16_t port) const {
|
|
65
|
+
return peers_.count(key(ip, port)) != 0;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
} // namespace librats::bittorrent
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file peer_list.h
|
|
5
|
+
* @brief The set of *known* peer addresses for a torrent (distinct from the live
|
|
6
|
+
* connections).
|
|
7
|
+
*
|
|
8
|
+
* Every discovery source — tracker, DHT, PEX, LSD, incoming — funnels addresses
|
|
9
|
+
* here; the Torrent then asks for connect_candidates() to dial. The list
|
|
10
|
+
* deduplicates, remembers which sources vouched for a peer, counts connection
|
|
11
|
+
* failures (so hopeless peers drift to the back and eventually drop out), and
|
|
12
|
+
* supports banning. Owned by one torrent on the reactor thread — not thread-safe.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
#include <cstddef>
|
|
16
|
+
#include <cstdint>
|
|
17
|
+
#include <string>
|
|
18
|
+
#include <unordered_map>
|
|
19
|
+
#include <utility>
|
|
20
|
+
#include <vector>
|
|
21
|
+
|
|
22
|
+
namespace librats::bittorrent {
|
|
23
|
+
|
|
24
|
+
enum class PeerSource : std::uint8_t {
|
|
25
|
+
Tracker = 1,
|
|
26
|
+
Dht = 2,
|
|
27
|
+
Pex = 4,
|
|
28
|
+
Lsd = 8,
|
|
29
|
+
Incoming = 16,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
class PeerList {
|
|
33
|
+
public:
|
|
34
|
+
struct Endpoint { std::string ip; std::uint16_t port; };
|
|
35
|
+
|
|
36
|
+
struct Peer {
|
|
37
|
+
std::string ip;
|
|
38
|
+
std::uint16_t port = 0;
|
|
39
|
+
std::uint8_t sources = 0;
|
|
40
|
+
bool connected = false;
|
|
41
|
+
bool connecting = false;
|
|
42
|
+
bool banned = false;
|
|
43
|
+
std::uint32_t fail_count = 0;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
static constexpr std::uint32_t kMaxFails = 5;
|
|
47
|
+
|
|
48
|
+
/// Add or merge a candidate. Returns true if it was newly created.
|
|
49
|
+
bool add(const std::string& ip, std::uint16_t port, PeerSource source);
|
|
50
|
+
|
|
51
|
+
/// Up to @p max eligible peers to dial (not connected/connecting/banned, and
|
|
52
|
+
/// under the failure limit), best first. The returned peers are marked
|
|
53
|
+
/// `connecting` so they aren't handed out again until resolved.
|
|
54
|
+
std::vector<Endpoint> connect_candidates(std::size_t max);
|
|
55
|
+
|
|
56
|
+
void set_connected(const std::string& ip, std::uint16_t port, bool connected);
|
|
57
|
+
void on_connect_failed(const std::string& ip, std::uint16_t port);
|
|
58
|
+
void ban(const std::string& ip, std::uint16_t port);
|
|
59
|
+
|
|
60
|
+
std::size_t size() const noexcept { return peers_.size(); }
|
|
61
|
+
std::size_t num_candidates() const; ///< count currently eligible to dial
|
|
62
|
+
bool contains(const std::string& ip, std::uint16_t port) const;
|
|
63
|
+
|
|
64
|
+
private:
|
|
65
|
+
static std::string key(const std::string& ip, std::uint16_t port) {
|
|
66
|
+
return ip + ":" + std::to_string(port);
|
|
67
|
+
}
|
|
68
|
+
bool eligible(const Peer& p) const noexcept {
|
|
69
|
+
return !p.connected && !p.connecting && !p.banned && p.fail_count < kMaxFails;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
std::unordered_map<std::string, Peer> peers_;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
} // namespace librats::bittorrent
|