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,402 +0,0 @@
|
|
|
1
|
-
#include "librats.h"
|
|
2
|
-
#include "librats_log_macros.h"
|
|
3
|
-
#include "sha1.h"
|
|
4
|
-
|
|
5
|
-
namespace librats {
|
|
6
|
-
|
|
7
|
-
// =========================================================================
|
|
8
|
-
// Peer Discovery Methods
|
|
9
|
-
// =========================================================================
|
|
10
|
-
|
|
11
|
-
bool RatsClient::start_dht_discovery(int dht_port) {
|
|
12
|
-
if (dht_client_ && dht_client_->is_running()) {
|
|
13
|
-
LOG_CLIENT_WARN("DHT discovery is already running");
|
|
14
|
-
return true;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
LOG_CLIENT_INFO("Starting DHT discovery on port " << dht_port <<
|
|
18
|
-
(bind_address_.empty() ? "" : " bound to " + bind_address_));
|
|
19
|
-
|
|
20
|
-
auto bootstrap_nodes = DhtClient::get_default_bootstrap_nodes();
|
|
21
|
-
|
|
22
|
-
// IPv4 DHT (also shared with the BitTorrent subsystem) - required.
|
|
23
|
-
dht_client_ = std::make_unique<DhtClient>(dht_port, bind_address_, data_directory_, AddressFamily::IPv4);
|
|
24
|
-
if (!dht_client_->start()) {
|
|
25
|
-
LOG_CLIENT_ERROR("Failed to start IPv4 DHT client");
|
|
26
|
-
dht_client_.reset();
|
|
27
|
-
return false;
|
|
28
|
-
}
|
|
29
|
-
if (!dht_client_->bootstrap(bootstrap_nodes)) {
|
|
30
|
-
LOG_CLIENT_WARN("Failed to bootstrap IPv4 DHT");
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// IPv6 DHT - best effort. Shares the same port via a V6ONLY socket. If the host has
|
|
34
|
-
// no usable IPv6 stack, socket creation fails and we simply run IPv4-only.
|
|
35
|
-
dht_client_v6_ = std::make_unique<DhtClient>(dht_port, bind_address_, data_directory_, AddressFamily::IPv6);
|
|
36
|
-
if (dht_client_v6_->start()) {
|
|
37
|
-
if (!dht_client_v6_->bootstrap(bootstrap_nodes)) {
|
|
38
|
-
LOG_CLIENT_WARN("Failed to bootstrap IPv6 DHT");
|
|
39
|
-
}
|
|
40
|
-
LOG_CLIENT_INFO("IPv6 DHT client started");
|
|
41
|
-
} else {
|
|
42
|
-
LOG_CLIENT_INFO("IPv6 DHT unavailable on this host, running IPv4-only");
|
|
43
|
-
dht_client_v6_.reset();
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Forward the DHT's UDP port through the router, in addition to the TCP peer
|
|
47
|
-
// port mapped at start(). Like libtorrent (which maps both the TCP listen port
|
|
48
|
-
// and the UDP DHT/uTP port per listen socket), this makes the node reachable by
|
|
49
|
-
// inbound DHT traffic behind NAT. No-op when port mapping is disabled; the
|
|
50
|
-
// mapping uses external==internal so outgoing queries and inbound packets share
|
|
51
|
-
// one public port. The backends wake their workers to install it immediately.
|
|
52
|
-
// Use the *actual* bound port: start() may have fallen back to an ephemeral one
|
|
53
|
-
// when the requested dht_port was taken.
|
|
54
|
-
uint16_t bound_dht_port = dht_client_->get_port();
|
|
55
|
-
if (bound_dht_port != 0) {
|
|
56
|
-
add_port_mapping(PortMapProtocol::UDP, bound_dht_port);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Start automatic peer discovery (this thread also performs the best-effort STUN probe
|
|
60
|
-
// that derives our BEP 42 node ID — see automatic_discovery_loop).
|
|
61
|
-
start_automatic_peer_discovery();
|
|
62
|
-
|
|
63
|
-
LOG_CLIENT_INFO("DHT discovery started successfully");
|
|
64
|
-
return true;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
void RatsClient::stop_dht_discovery() {
|
|
68
|
-
if (!dht_client_ && !dht_client_v6_) {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
LOG_CLIENT_INFO("Stopping DHT discovery");
|
|
73
|
-
|
|
74
|
-
// Stop automatic peer discovery
|
|
75
|
-
stop_automatic_peer_discovery();
|
|
76
|
-
|
|
77
|
-
if (dht_client_) {
|
|
78
|
-
dht_client_->stop();
|
|
79
|
-
dht_client_.reset();
|
|
80
|
-
}
|
|
81
|
-
if (dht_client_v6_) {
|
|
82
|
-
dht_client_v6_->stop();
|
|
83
|
-
dht_client_v6_.reset();
|
|
84
|
-
}
|
|
85
|
-
LOG_CLIENT_INFO("DHT discovery stopped");
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
bool RatsClient::find_peers_by_hash(const std::string& content_hash, std::function<void(const std::vector<std::string>&)> callback) {
|
|
89
|
-
if (!is_dht_running()) {
|
|
90
|
-
LOG_CLIENT_ERROR("DHT client not running");
|
|
91
|
-
return false;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (content_hash.length() != CONTENT_HASH_HEX_LENGTH) {
|
|
95
|
-
LOG_CLIENT_ERROR("Invalid content hash length: " << content_hash.length() << " (expected " << CONTENT_HASH_HEX_LENGTH << ")");
|
|
96
|
-
return false;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
LOG_CLIENT_INFO("Finding peers for content hash: " << content_hash);
|
|
100
|
-
|
|
101
|
-
InfoHash info_hash = hex_to_node_id(content_hash);
|
|
102
|
-
|
|
103
|
-
// Shared wrapper: discovered peers (IPv4 or IPv6) are delivered through the same callback.
|
|
104
|
-
PeerDiscoveryCallback peer_callback = [callback](const std::vector<Peer>& peers, const InfoHash&) {
|
|
105
|
-
std::vector<std::string> peer_addresses;
|
|
106
|
-
peer_addresses.reserve(peers.size());
|
|
107
|
-
for (const auto& peer : peers) {
|
|
108
|
-
peer_addresses.emplace_back(peer.ip + ":" + std::to_string(peer.port));
|
|
109
|
-
}
|
|
110
|
-
if (callback) {
|
|
111
|
-
callback(peer_addresses);
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
// Fan out to both Kademlia networks; succeed if at least one accepts the search.
|
|
116
|
-
bool started = false;
|
|
117
|
-
if (dht_client_ && dht_client_->is_running()) {
|
|
118
|
-
started |= dht_client_->find_peers(info_hash, peer_callback);
|
|
119
|
-
}
|
|
120
|
-
if (dht_client_v6_ && dht_client_v6_->is_running()) {
|
|
121
|
-
started |= dht_client_v6_->find_peers(info_hash, peer_callback);
|
|
122
|
-
}
|
|
123
|
-
return started;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
bool RatsClient::announce_for_hash(const std::string& content_hash, uint16_t port,
|
|
127
|
-
std::function<void(const std::vector<std::string>&)> callback) {
|
|
128
|
-
if (!is_dht_running()) {
|
|
129
|
-
LOG_CLIENT_ERROR("DHT client not running");
|
|
130
|
-
return false;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
if (content_hash.length() != CONTENT_HASH_HEX_LENGTH) {
|
|
134
|
-
LOG_CLIENT_ERROR("Invalid content hash length: " << content_hash.length() << " (expected " << CONTENT_HASH_HEX_LENGTH << ")");
|
|
135
|
-
return false;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
if (port == 0) {
|
|
139
|
-
port = listen_port_;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
LOG_CLIENT_INFO("Announcing for content hash: " << content_hash << " on port " << port
|
|
143
|
-
<< (callback ? " with peer callback" : ""));
|
|
144
|
-
|
|
145
|
-
InfoHash info_hash = hex_to_node_id(content_hash);
|
|
146
|
-
|
|
147
|
-
// Create wrapper callback that converts Peer to string addresses (if callback provided)
|
|
148
|
-
PeerDiscoveryCallback peer_callback = nullptr;
|
|
149
|
-
if (callback) {
|
|
150
|
-
peer_callback = [callback](const std::vector<Peer>& peers, const InfoHash& hash) {
|
|
151
|
-
std::vector<std::string> peer_addresses;
|
|
152
|
-
peer_addresses.reserve(peers.size());
|
|
153
|
-
for (const auto& peer : peers) {
|
|
154
|
-
peer_addresses.push_back(peer.ip + ":" + std::to_string(peer.port));
|
|
155
|
-
}
|
|
156
|
-
callback(peer_addresses);
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Announce on both Kademlia networks so IPv4 and IPv6 peers can both find us.
|
|
161
|
-
bool started = false;
|
|
162
|
-
if (dht_client_ && dht_client_->is_running()) {
|
|
163
|
-
started |= dht_client_->announce_peer(info_hash, port, peer_callback);
|
|
164
|
-
}
|
|
165
|
-
if (dht_client_v6_ && dht_client_v6_->is_running()) {
|
|
166
|
-
started |= dht_client_v6_->announce_peer(info_hash, port, peer_callback);
|
|
167
|
-
}
|
|
168
|
-
return started;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
bool RatsClient::is_dht_running() const {
|
|
172
|
-
return (dht_client_ && dht_client_->is_running()) ||
|
|
173
|
-
(dht_client_v6_ && dht_client_v6_->is_running());
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
size_t RatsClient::get_dht_routing_table_size() const {
|
|
177
|
-
size_t total = 0;
|
|
178
|
-
if (dht_client_) {
|
|
179
|
-
total += dht_client_->get_routing_table_size();
|
|
180
|
-
}
|
|
181
|
-
if (dht_client_v6_) {
|
|
182
|
-
total += dht_client_v6_->get_routing_table_size();
|
|
183
|
-
}
|
|
184
|
-
return total;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
void RatsClient::handle_dht_peer_discovery(const std::vector<Peer>& peers, const InfoHash& info_hash) {
|
|
188
|
-
LOG_CLIENT_INFO("DHT discovered " << peers.size() << " peers for info hash: " << node_id_to_hex(info_hash));
|
|
189
|
-
|
|
190
|
-
// Auto-connect to discovered peers
|
|
191
|
-
for (const auto& peer : peers) {
|
|
192
|
-
if (!can_connect_to_peer(peer.ip, peer.port)) {
|
|
193
|
-
continue;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
LOG_CLIENT_DEBUG("Attempting to connect to discovered peer: " << peer.ip << ":" << peer.port);
|
|
197
|
-
|
|
198
|
-
// Try to connect to the peer (non-blocking, managed thread for graceful shutdown)
|
|
199
|
-
add_managed_thread(std::thread([this, peer]() {
|
|
200
|
-
if (connect_to_peer(peer.ip, peer.port)) {
|
|
201
|
-
LOG_CLIENT_INFO("Successfully connected to DHT discovered peer: " << peer.ip << ":" << peer.port);
|
|
202
|
-
} else {
|
|
203
|
-
LOG_CLIENT_DEBUG("Failed to connect to DHT discovered peer: " << peer.ip << ":" << peer.port);
|
|
204
|
-
}
|
|
205
|
-
}), "dht-connect-" + peer.ip);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
void RatsClient::start_automatic_peer_discovery() {
|
|
210
|
-
if (auto_discovery_running_.load()) {
|
|
211
|
-
LOG_CLIENT_WARN("Automatic peer discovery is already running");
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
LOG_CLIENT_INFO("Starting automatic rats peer discovery");
|
|
216
|
-
auto_discovery_running_.store(true);
|
|
217
|
-
auto_discovery_thread_ = std::thread(&RatsClient::automatic_discovery_loop, this);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
void RatsClient::stop_automatic_peer_discovery() {
|
|
221
|
-
if (!auto_discovery_running_.load()) {
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
LOG_CLIENT_INFO("Stopping automatic peer discovery");
|
|
226
|
-
auto_discovery_running_.store(false);
|
|
227
|
-
|
|
228
|
-
if (auto_discovery_thread_.joinable()) {
|
|
229
|
-
auto_discovery_thread_.join();
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
LOG_CLIENT_INFO("Automatic peer discovery stopped");
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
bool RatsClient::is_automatic_discovery_running() const {
|
|
236
|
-
return auto_discovery_running_.load();
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
std::chrono::seconds RatsClient::calculate_discovery_interval() const {
|
|
240
|
-
int peer_count = get_peer_count();
|
|
241
|
-
|
|
242
|
-
// No peers - aggressive discovery
|
|
243
|
-
if (peer_count == 0) {
|
|
244
|
-
return std::chrono::seconds(15);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// Calculate fill ratio
|
|
248
|
-
float fill_ratio = static_cast<float>(peer_count) / static_cast<float>(max_peers_);
|
|
249
|
-
|
|
250
|
-
// Graduated intervals based on fill ratio
|
|
251
|
-
if (fill_ratio < 0.25f) {
|
|
252
|
-
// Less than 25% full - still fairly aggressive
|
|
253
|
-
return std::chrono::seconds(60); // 1 minute
|
|
254
|
-
} else if (fill_ratio < 0.50f) {
|
|
255
|
-
// 25-50% full - moderate
|
|
256
|
-
return std::chrono::seconds(180); // 3 minutes
|
|
257
|
-
} else if (fill_ratio < 0.75f) {
|
|
258
|
-
// 50-75% full - relaxed
|
|
259
|
-
return std::chrono::seconds(600); // 10 minutes
|
|
260
|
-
} else {
|
|
261
|
-
// 75-100% full - very relaxed (mostly just re-announcing)
|
|
262
|
-
return std::chrono::seconds(1800); // 30 minutes
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
void RatsClient::automatic_discovery_loop() {
|
|
267
|
-
LOG_CLIENT_INFO("Automatic peer discovery loop started");
|
|
268
|
-
|
|
269
|
-
// Best-effort: discover our public IP via STUN and derive a BEP 42 node ID from it BEFORE
|
|
270
|
-
// the initial bootstrap delay below. The DHT starts receiving KRPC responses (each carrying
|
|
271
|
-
// our address in the "ip" field) immediately on bootstrap, and that in-DHT vote can reach
|
|
272
|
-
// EXTERNAL_IP_VOTE_THRESHOLD within a few seconds. Probing STUN first lets set_external_ip()
|
|
273
|
-
// adopt the address and regenerate the node ID up front, so the DHT bootstraps under the
|
|
274
|
-
// correct ID and the ip-field voting silently confirms the already-adopted address instead
|
|
275
|
-
// of racing it to consensus. The voting remains the fallback when STUN is unavailable or the
|
|
276
|
-
// address later changes.
|
|
277
|
-
//
|
|
278
|
-
// This runs on the discovery thread (not a standalone one) on purpose: stop_dht_discovery()
|
|
279
|
-
// joins this thread via stop_automatic_peer_discovery() BEFORE resetting the DHT clients, so
|
|
280
|
-
// set_external_ip() can never touch a destroyed DhtClient.
|
|
281
|
-
if (auto_discovery_running_.load() && running_.load()) {
|
|
282
|
-
auto mapped = discover_public_address("stun.l.google.com", 19302, 4000);
|
|
283
|
-
if (mapped) {
|
|
284
|
-
// set_external_ip validates the address family, so feeding both instances is safe:
|
|
285
|
-
// only the matching-family DHT adopts it. (A default IPv4 STUN server yields an IPv4
|
|
286
|
-
// address; the IPv6 node ID is learned organically from IPv6 DHT responses.)
|
|
287
|
-
if (dht_client_) {
|
|
288
|
-
dht_client_->set_external_ip(mapped->address);
|
|
289
|
-
}
|
|
290
|
-
if (dht_client_v6_) {
|
|
291
|
-
dht_client_v6_->set_external_ip(mapped->address);
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// Initial delay to let DHT bootstrap
|
|
297
|
-
{
|
|
298
|
-
std::unique_lock<std::mutex> lock(shutdown_mutex_);
|
|
299
|
-
if (shutdown_cv_.wait_for(lock, std::chrono::seconds(INITIAL_DISCOVERY_DELAY_SECONDS), [this] { return !auto_discovery_running_.load() || !running_.load(); })) {
|
|
300
|
-
LOG_CLIENT_INFO("Automatic peer discovery loop stopped during initial delay");
|
|
301
|
-
return;
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
// Announce immediately - this also discovers peers during traversal
|
|
306
|
-
announce_rats_peer();
|
|
307
|
-
|
|
308
|
-
auto last_announce = std::chrono::steady_clock::now();
|
|
309
|
-
|
|
310
|
-
while (auto_discovery_running_.load()) {
|
|
311
|
-
auto now = std::chrono::steady_clock::now();
|
|
312
|
-
|
|
313
|
-
// Announce combines both announcing our presence and discovering peers
|
|
314
|
-
// Interval scales based on peer count: aggressive when empty, relaxed when nearly full
|
|
315
|
-
auto interval = calculate_discovery_interval();
|
|
316
|
-
|
|
317
|
-
if (now - last_announce >= interval) {
|
|
318
|
-
LOG_CLIENT_DEBUG("Discovery interval: " << interval.count() << "s (peers: "
|
|
319
|
-
<< get_peer_count() << "/" << max_peers_ << ")");
|
|
320
|
-
announce_rats_peer();
|
|
321
|
-
last_announce = now;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
// Use conditional variable for responsive shutdown
|
|
325
|
-
{
|
|
326
|
-
std::unique_lock<std::mutex> lock(shutdown_mutex_);
|
|
327
|
-
if (shutdown_cv_.wait_for(lock, std::chrono::milliseconds(500), [this] { return !auto_discovery_running_.load() || !running_.load(); })) {
|
|
328
|
-
break;
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
LOG_CLIENT_INFO("Automatic peer discovery loop stopped");
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
void RatsClient::announce_rats_peer() {
|
|
337
|
-
if (!dht_client_ || !dht_client_->is_running()) {
|
|
338
|
-
LOG_CLIENT_WARN("DHT client not running, cannot announce peer");
|
|
339
|
-
return;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
std::string discovery_hash = get_discovery_hash();
|
|
343
|
-
|
|
344
|
-
// Advertise the mapped public TCP port when UPnP/NAT-PMP has established one,
|
|
345
|
-
// so WAN peers connect to (external_ip, external_port) rather than our NATed
|
|
346
|
-
// local listen port. Falls back to listen_port_ when no mapping is active.
|
|
347
|
-
// (Mirrors libtorrent feeding the port-mapping result into what it announces.)
|
|
348
|
-
uint16_t announce_port = get_advertised_port();
|
|
349
|
-
LOG_CLIENT_INFO("Announcing peer for discovery hash: " << discovery_hash << " on port " << announce_port);
|
|
350
|
-
|
|
351
|
-
InfoHash info_hash = hex_to_node_id(discovery_hash);
|
|
352
|
-
|
|
353
|
-
// Skip only if every running DHT network already has this announce in flight.
|
|
354
|
-
// (announce_peer() also dedups internally, so this is just to avoid redundant work.)
|
|
355
|
-
bool v4_busy = !dht_client_ || !dht_client_->is_running() || dht_client_->is_announce_active(info_hash);
|
|
356
|
-
bool v6_busy = !dht_client_v6_ || !dht_client_v6_->is_running() || dht_client_v6_->is_announce_active(info_hash);
|
|
357
|
-
if (v4_busy && v6_busy) {
|
|
358
|
-
LOG_CLIENT_WARN("Announce already in progress for info hash: " << node_id_to_hex(info_hash));
|
|
359
|
-
return;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
// Use announce with callback - combines announce and find_peers in one traversal
|
|
363
|
-
// Peers discovered during traversal will be returned through the callback
|
|
364
|
-
if (announce_for_hash(discovery_hash, announce_port, [this, info_hash](const std::vector<std::string>& peer_addresses) {
|
|
365
|
-
LOG_CLIENT_INFO("Announce discovered " << peer_addresses.size() << " peers during traversal");
|
|
366
|
-
|
|
367
|
-
// Convert peer addresses to Peer objects for handle_dht_peer_discovery()
|
|
368
|
-
std::vector<Peer> peers;
|
|
369
|
-
peers.reserve(peer_addresses.size());
|
|
370
|
-
for (const auto& peer_address : peer_addresses) {
|
|
371
|
-
std::string ip;
|
|
372
|
-
int port;
|
|
373
|
-
if (parse_address_string(peer_address, ip, port)) {
|
|
374
|
-
peers.push_back(Peer(ip, port));
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
// Auto-connect to discovered peers
|
|
379
|
-
if (!peers.empty()) {
|
|
380
|
-
handle_dht_peer_discovery(peers, info_hash);
|
|
381
|
-
}
|
|
382
|
-
})) {
|
|
383
|
-
LOG_CLIENT_DEBUG("Successfully started announce with peer discovery for discovery hash");
|
|
384
|
-
} else {
|
|
385
|
-
LOG_CLIENT_WARN("Failed to announce peer for discovery");
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
std::string RatsClient::get_discovery_hash() const {
|
|
390
|
-
std::lock_guard<std::mutex> lock(protocol_config_mutex_);
|
|
391
|
-
// Generate discovery hash based on current protocol configuration
|
|
392
|
-
std::string discovery_string = custom_protocol_name_ + "_peer_discovery_v" + custom_protocol_version_;
|
|
393
|
-
return SHA1::hash(discovery_string);
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
std::string RatsClient::get_rats_peer_discovery_hash() {
|
|
397
|
-
// Well-known hash for rats peer discovery
|
|
398
|
-
// Compute SHA1 hash of "rats_peer_discovery_v1.0"
|
|
399
|
-
return SHA1::hash("rats_peer_discovery_v1.0");
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
}
|
|
@@ -1,275 +0,0 @@
|
|
|
1
|
-
#include "librats.h"
|
|
2
|
-
#include "librats_log_macros.h"
|
|
3
|
-
|
|
4
|
-
namespace librats {
|
|
5
|
-
|
|
6
|
-
// =========================================================================
|
|
7
|
-
// Encryption Functionality - Noise Protocol Implementation
|
|
8
|
-
// =========================================================================
|
|
9
|
-
|
|
10
|
-
void RatsClient::initialize_noise_keypair() {
|
|
11
|
-
std::lock_guard<std::mutex> lock(encryption_mutex_);
|
|
12
|
-
if (!noise_keypair_initialized_) {
|
|
13
|
-
rats::noise_generate_keypair(noise_static_keypair_);
|
|
14
|
-
noise_keypair_initialized_ = true;
|
|
15
|
-
LOG_CLIENT_INFO("Noise Protocol static keypair generated");
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
bool RatsClient::initialize_encryption(bool enable) {
|
|
20
|
-
std::lock_guard<std::mutex> lock(encryption_mutex_);
|
|
21
|
-
encryption_enabled_ = enable;
|
|
22
|
-
|
|
23
|
-
if (enable && !noise_keypair_initialized_) {
|
|
24
|
-
rats::noise_generate_keypair(noise_static_keypair_);
|
|
25
|
-
noise_keypair_initialized_ = true;
|
|
26
|
-
LOG_CLIENT_INFO("Noise Protocol initialized with new static keypair");
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
LOG_CLIENT_INFO("Encryption " << (enable ? "enabled" : "disabled"));
|
|
30
|
-
return true;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
void RatsClient::set_encryption_enabled(bool enabled) {
|
|
34
|
-
std::lock_guard<std::mutex> lock(encryption_mutex_);
|
|
35
|
-
encryption_enabled_ = enabled;
|
|
36
|
-
|
|
37
|
-
if (enabled && !noise_keypair_initialized_) {
|
|
38
|
-
rats::noise_generate_keypair(noise_static_keypair_);
|
|
39
|
-
noise_keypair_initialized_ = true;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
LOG_CLIENT_DEBUG("Encryption set to " << (enabled ? "enabled" : "disabled"));
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
bool RatsClient::is_encryption_enabled() const {
|
|
46
|
-
std::lock_guard<std::mutex> lock(encryption_mutex_);
|
|
47
|
-
return encryption_enabled_;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
bool RatsClient::is_peer_encrypted(const std::string& peer_id) const {
|
|
51
|
-
std::lock_guard<std::mutex> lock(peers_mutex_);
|
|
52
|
-
auto it = peers_.find(peer_id);
|
|
53
|
-
if (it != peers_.end()) {
|
|
54
|
-
return it->second.noise_handshake_completed &&
|
|
55
|
-
it->second.send_cipher &&
|
|
56
|
-
it->second.recv_cipher;
|
|
57
|
-
}
|
|
58
|
-
return false;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
bool RatsClient::set_noise_static_keypair(const uint8_t private_key[32]) {
|
|
62
|
-
std::lock_guard<std::mutex> lock(encryption_mutex_);
|
|
63
|
-
|
|
64
|
-
memcpy(noise_static_keypair_.private_key, private_key, 32);
|
|
65
|
-
rats::noise_derive_public_key(private_key, noise_static_keypair_.public_key);
|
|
66
|
-
noise_static_keypair_.has_keys = true;
|
|
67
|
-
noise_keypair_initialized_ = true;
|
|
68
|
-
|
|
69
|
-
LOG_CLIENT_INFO("Noise Protocol static keypair set from provided private key");
|
|
70
|
-
return true;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
std::vector<uint8_t> RatsClient::get_noise_static_public_key() const {
|
|
74
|
-
std::lock_guard<std::mutex> lock(encryption_mutex_);
|
|
75
|
-
|
|
76
|
-
if (!noise_keypair_initialized_) {
|
|
77
|
-
return std::vector<uint8_t>();
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return std::vector<uint8_t>(noise_static_keypair_.public_key,
|
|
81
|
-
noise_static_keypair_.public_key + 32);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
std::vector<uint8_t> RatsClient::get_peer_noise_public_key(const std::string& peer_id) const {
|
|
85
|
-
std::lock_guard<std::mutex> lock(peers_mutex_);
|
|
86
|
-
auto it = peers_.find(peer_id);
|
|
87
|
-
if (it != peers_.end() && it->second.noise_handshake_completed) {
|
|
88
|
-
return it->second.remote_static_key;
|
|
89
|
-
}
|
|
90
|
-
return std::vector<uint8_t>();
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
std::vector<uint8_t> RatsClient::get_peer_handshake_hash(const std::string& peer_id) const {
|
|
94
|
-
// Handshake hash is not stored after handshake for memory efficiency
|
|
95
|
-
// This could be added to RatsPeer if needed for channel binding
|
|
96
|
-
(void)peer_id;
|
|
97
|
-
return std::vector<uint8_t>();
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// =========================================================================
|
|
101
|
-
// Async Noise Handshake (non-blocking, driven by io_loop)
|
|
102
|
-
// =========================================================================
|
|
103
|
-
|
|
104
|
-
/*
|
|
105
|
-
* Noise XX pattern (3 messages):
|
|
106
|
-
* Initiator: write msg0 → read msg1 → write msg2 → split
|
|
107
|
-
* Responder: read msg0 → write msg1 → read msg2 → split
|
|
108
|
-
*
|
|
109
|
-
* noise_step tracks where we are in this sequence:
|
|
110
|
-
* Initiator: 0 = need write, 1 = need read, 2 = need write, 3 = done
|
|
111
|
-
* Responder: 0 = need read, 1 = need write, 2 = need read, 3 = done
|
|
112
|
-
*
|
|
113
|
-
* start_noise_handshake_async() initialises noise_hs and writes the first
|
|
114
|
-
* outgoing message (if initiator). Subsequent messages are processed by
|
|
115
|
-
* handle_noise_frame() which is called from handle_readable when
|
|
116
|
-
* handshake_state == NOISE_PENDING.
|
|
117
|
-
*/
|
|
118
|
-
|
|
119
|
-
void RatsClient::start_noise_handshake_async(RatsPeer& peer) {
|
|
120
|
-
LOG_CLIENT_INFO("Starting async Noise handshake for " << peer.peer_id
|
|
121
|
-
<< " (initiator: " << peer.is_outgoing << ")");
|
|
122
|
-
|
|
123
|
-
// Get our static keypair
|
|
124
|
-
rats::NoiseKeyPair static_keypair;
|
|
125
|
-
{
|
|
126
|
-
std::lock_guard<std::mutex> lock(encryption_mutex_);
|
|
127
|
-
if (!noise_keypair_initialized_) {
|
|
128
|
-
rats::noise_generate_keypair(noise_static_keypair_);
|
|
129
|
-
noise_keypair_initialized_ = true;
|
|
130
|
-
}
|
|
131
|
-
memcpy(static_keypair.private_key, noise_static_keypair_.private_key, 32);
|
|
132
|
-
memcpy(static_keypair.public_key, noise_static_keypair_.public_key, 32);
|
|
133
|
-
static_keypair.has_keys = true;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Allocate handshake state on the peer's IO context
|
|
137
|
-
peer.io_.noise_hs = std::make_unique<rats::NoiseHandshakeState>();
|
|
138
|
-
peer.io_.noise_step = 0;
|
|
139
|
-
|
|
140
|
-
auto err = peer.io_.noise_hs->initialize(peer.is_outgoing, &static_keypair);
|
|
141
|
-
if (err != rats::NoiseError::OK) {
|
|
142
|
-
LOG_CLIENT_ERROR("Failed to initialise Noise handshake: " << static_cast<int>(err));
|
|
143
|
-
peer.handshake_state = RatsPeer::HandshakeState::FAILED;
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Initiator sends message 0 immediately
|
|
148
|
-
if (peer.is_outgoing) {
|
|
149
|
-
uint8_t msg_buf[256];
|
|
150
|
-
size_t msg_len = sizeof(msg_buf);
|
|
151
|
-
err = peer.io_.noise_hs->write_message(nullptr, 0, msg_buf, &msg_len);
|
|
152
|
-
if (err != rats::NoiseError::OK) {
|
|
153
|
-
LOG_CLIENT_ERROR("Failed to write Noise msg 0: " << static_cast<int>(err));
|
|
154
|
-
peer.handshake_state = RatsPeer::HandshakeState::FAILED;
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Enqueue as a length-prefixed frame (same framing as data messages)
|
|
159
|
-
std::vector<uint8_t> payload(msg_buf, msg_buf + msg_len);
|
|
160
|
-
enqueue_message_unlocked(peer, payload);
|
|
161
|
-
peer.io_.noise_step = 1; // next: need to read msg 1
|
|
162
|
-
LOG_CLIENT_DEBUG("Sent Noise msg 0 (" << msg_len << " bytes) to " << peer.peer_id);
|
|
163
|
-
}
|
|
164
|
-
// Responder waits for msg 0 from initiator (noise_step stays 0)
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
bool RatsClient::handle_noise_frame(RatsPeer& peer) {
|
|
168
|
-
// The caller (handle_readable) has already verified that a complete
|
|
169
|
-
// length-prefixed frame is available in the receive buffer, but hasn't
|
|
170
|
-
// consumed it yet. We read the payload from recv_buf (skip 4-byte length).
|
|
171
|
-
auto& recv_buf = peer.io_.recv_buffer;
|
|
172
|
-
|
|
173
|
-
// Read payload length
|
|
174
|
-
uint32_t net_len;
|
|
175
|
-
memcpy(&net_len, recv_buf.data(), 4);
|
|
176
|
-
uint32_t frame_len = ntohl(net_len);
|
|
177
|
-
|
|
178
|
-
const uint8_t* frame_data = recv_buf.data() + 4;
|
|
179
|
-
|
|
180
|
-
if (!peer.io_.noise_hs) {
|
|
181
|
-
LOG_CLIENT_ERROR("Noise frame received but no handshake state for " << peer.peer_id);
|
|
182
|
-
return false;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
auto& hs = *peer.io_.noise_hs;
|
|
186
|
-
bool is_initiator = peer.is_outgoing;
|
|
187
|
-
rats::NoiseError err;
|
|
188
|
-
uint8_t out_buf[256];
|
|
189
|
-
size_t out_len;
|
|
190
|
-
|
|
191
|
-
/*
|
|
192
|
-
* Step table (noise_step → action):
|
|
193
|
-
* Initiator: 0=write, 1=read, 2=write, 3=done
|
|
194
|
-
* Responder: 0=read, 1=write, 2=read, 3=done
|
|
195
|
-
*
|
|
196
|
-
* This function is only called when we received a frame, so the current
|
|
197
|
-
* step must expect a "read".
|
|
198
|
-
*/
|
|
199
|
-
|
|
200
|
-
// ── Read the incoming Noise message ──
|
|
201
|
-
out_len = sizeof(out_buf);
|
|
202
|
-
err = hs.read_message(frame_data, frame_len, out_buf, &out_len);
|
|
203
|
-
if (err != rats::NoiseError::OK) {
|
|
204
|
-
LOG_CLIENT_ERROR("Noise read_message failed (step " << peer.io_.noise_step
|
|
205
|
-
<< "): " << static_cast<int>(err));
|
|
206
|
-
return false;
|
|
207
|
-
}
|
|
208
|
-
LOG_CLIENT_DEBUG("Read Noise msg (step " << peer.io_.noise_step
|
|
209
|
-
<< ", " << frame_len << " bytes) from " << peer.peer_id);
|
|
210
|
-
|
|
211
|
-
peer.io_.noise_step++;
|
|
212
|
-
|
|
213
|
-
// ── If there's a reply to write, do it now ──
|
|
214
|
-
bool need_write = false;
|
|
215
|
-
if (is_initiator) {
|
|
216
|
-
// Initiator writes on steps 0 and 2 → after reading (step becomes 2), write
|
|
217
|
-
need_write = (peer.io_.noise_step == 2);
|
|
218
|
-
} else {
|
|
219
|
-
// Responder writes on step 1 → after reading (step becomes 1), write
|
|
220
|
-
need_write = (peer.io_.noise_step == 1);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
if (need_write) {
|
|
224
|
-
out_len = sizeof(out_buf);
|
|
225
|
-
err = hs.write_message(nullptr, 0, out_buf, &out_len);
|
|
226
|
-
if (err != rats::NoiseError::OK) {
|
|
227
|
-
LOG_CLIENT_ERROR("Noise write_message failed (step " << peer.io_.noise_step
|
|
228
|
-
<< "): " << static_cast<int>(err));
|
|
229
|
-
return false;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
std::vector<uint8_t> payload(out_buf, out_buf + out_len);
|
|
233
|
-
enqueue_message_unlocked(peer, payload);
|
|
234
|
-
LOG_CLIENT_DEBUG("Sent Noise msg (step " << peer.io_.noise_step
|
|
235
|
-
<< ", " << out_len << " bytes) to " << peer.peer_id);
|
|
236
|
-
peer.io_.noise_step++;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// ── Check if handshake is complete ──
|
|
240
|
-
if (hs.is_handshake_complete()) {
|
|
241
|
-
auto send_cipher = std::make_shared<rats::NoiseCipherState>();
|
|
242
|
-
auto recv_cipher = std::make_shared<rats::NoiseCipherState>();
|
|
243
|
-
|
|
244
|
-
err = hs.split(*send_cipher, *recv_cipher);
|
|
245
|
-
if (err != rats::NoiseError::OK) {
|
|
246
|
-
LOG_CLIENT_ERROR("Noise split failed: " << static_cast<int>(err));
|
|
247
|
-
return false;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// Store ciphers and remote static key
|
|
251
|
-
peer.send_cipher = std::move(send_cipher);
|
|
252
|
-
peer.recv_cipher = std::move(recv_cipher);
|
|
253
|
-
peer.noise_handshake_completed = true;
|
|
254
|
-
|
|
255
|
-
if (hs.has_remote_static()) {
|
|
256
|
-
const uint8_t* remote_key = hs.get_remote_static_public();
|
|
257
|
-
peer.remote_static_key.assign(remote_key, remote_key + 32);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// Free handshake state (no longer needed)
|
|
261
|
-
peer.io_.noise_hs.reset();
|
|
262
|
-
peer.io_.noise_step = 0;
|
|
263
|
-
|
|
264
|
-
// Mark handshake completed
|
|
265
|
-
peer.handshake_state = RatsPeer::HandshakeState::COMPLETED;
|
|
266
|
-
validated_peer_count_.fetch_add(1, std::memory_order_relaxed);
|
|
267
|
-
log_handshake_completion_unlocked(peer);
|
|
268
|
-
|
|
269
|
-
LOG_CLIENT_INFO("Noise handshake completed with " << peer.peer_id);
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
return true;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
} // namespace librats
|