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,7 +1,8 @@
|
|
|
1
|
-
#include "mdns.h"
|
|
2
|
-
#include "
|
|
3
|
-
#include "
|
|
4
|
-
#include "
|
|
1
|
+
#include "librats/mdns/mdns.h"
|
|
2
|
+
#include "librats/mdns/log.h"
|
|
3
|
+
#include "librats/util/network_utils.h"
|
|
4
|
+
#include "librats/util/os.h"
|
|
5
|
+
#include "librats/core/socket.h"
|
|
5
6
|
#include <algorithm>
|
|
6
7
|
#include <random>
|
|
7
8
|
#include <sstream>
|
|
@@ -26,7 +27,7 @@ MdnsClient::MdnsClient(const std::string& service_instance_name, uint16_t servic
|
|
|
26
27
|
: service_instance_name_(service_instance_name),
|
|
27
28
|
service_port_(service_port),
|
|
28
29
|
service_type_(LIBRATS_SERVICE_TYPE), // Default service type
|
|
29
|
-
multicast_socket_(
|
|
30
|
+
multicast_socket_(RATS_INVALID_SOCKET),
|
|
30
31
|
running_(false),
|
|
31
32
|
announcing_(false),
|
|
32
33
|
discovering_(false),
|
|
@@ -90,11 +91,11 @@ void MdnsClient::stop() {
|
|
|
90
91
|
|
|
91
92
|
// Trigger immediate shutdown of all background threads
|
|
92
93
|
shutdown_immediate();
|
|
93
|
-
|
|
94
|
-
//
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
//
|
|
94
|
+
|
|
95
|
+
// Wait for threads to finish. They must be gone before the socket is closed:
|
|
96
|
+
// the receiver is waiting on it, so closing it first would race with that wait.
|
|
97
|
+
// shutdown_immediate() has already signalled the wakeup pipe, so the wait is
|
|
98
|
+
// over as soon as the scheduler gets to it rather than at the next timeout.
|
|
98
99
|
if (receiver_thread_.joinable()) {
|
|
99
100
|
receiver_thread_.join();
|
|
100
101
|
}
|
|
@@ -106,6 +107,9 @@ void MdnsClient::stop() {
|
|
|
106
107
|
if (querier_thread_.joinable()) {
|
|
107
108
|
querier_thread_.join();
|
|
108
109
|
}
|
|
110
|
+
|
|
111
|
+
// Now that nothing else touches it, close the socket
|
|
112
|
+
close_multicast_socket();
|
|
109
113
|
|
|
110
114
|
// Clear discovered services
|
|
111
115
|
{
|
|
@@ -124,8 +128,11 @@ void MdnsClient::shutdown_immediate() {
|
|
|
124
128
|
discovering_.store(false);
|
|
125
129
|
running_.store(false);
|
|
126
130
|
|
|
127
|
-
// Notify all waiting threads to wake up immediately
|
|
131
|
+
// Notify all waiting threads to wake up immediately. The announcer and querier
|
|
132
|
+
// sleep on the condition variable; the receiver is parked in a select() on the
|
|
133
|
+
// multicast socket and only the wakeup pipe can break that.
|
|
128
134
|
shutdown_cv_.notify_all();
|
|
135
|
+
receiver_wakeup_.signal();
|
|
129
136
|
}
|
|
130
137
|
|
|
131
138
|
bool MdnsClient::is_running() const {
|
|
@@ -324,7 +331,7 @@ bool MdnsClient::create_multicast_socket() {
|
|
|
324
331
|
LOG_MDNS_ERROR("Failed to bind to mDNS port " << MDNS_PORT << " (error: " << strerror(errno) << ")");
|
|
325
332
|
#endif
|
|
326
333
|
close_socket(multicast_socket_);
|
|
327
|
-
multicast_socket_ =
|
|
334
|
+
multicast_socket_ = RATS_INVALID_SOCKET;
|
|
328
335
|
return false;
|
|
329
336
|
}
|
|
330
337
|
|
|
@@ -419,46 +426,74 @@ void MdnsClient::close_multicast_socket() {
|
|
|
419
426
|
if (librats::is_valid_socket(multicast_socket_)) {
|
|
420
427
|
leave_multicast_group();
|
|
421
428
|
librats::close_socket(multicast_socket_, true);
|
|
422
|
-
multicast_socket_ =
|
|
429
|
+
multicast_socket_ = RATS_INVALID_SOCKET;
|
|
423
430
|
}
|
|
424
431
|
}
|
|
425
432
|
|
|
426
433
|
void MdnsClient::receiver_loop() {
|
|
427
434
|
LOG_MDNS_DEBUG("mDNS receiver loop started");
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
435
|
+
|
|
436
|
+
// stop() must be able to wind this loop down and join it *before* the socket is
|
|
437
|
+
// closed — closing an fd out from under a blocked recvfrom() races with it, since
|
|
438
|
+
// the number can be handed to another thread's socket()/open() the moment it is
|
|
439
|
+
// freed. The wakeup pipe is what makes that possible without polling: the wait
|
|
440
|
+
// watches it alongside the multicast socket, and shutdown_immediate() signals it.
|
|
441
|
+
//
|
|
442
|
+
// Waiting on a timeout instead would cost a wakeup per interval for the entire
|
|
443
|
+
// life of the process. On an idle node that is the *only* work being done, and it
|
|
444
|
+
// is paid per MdnsClient — measured at ~0.1 % of a core each with a 100 ms poll.
|
|
445
|
+
const socket_t interrupt_fd = receiver_wakeup_.fd();
|
|
446
|
+
|
|
447
|
+
// Only if the pipe could not be created: then there is nothing to interrupt the
|
|
448
|
+
// wait, so fall back to polling rather than to a blocking receive that stop()
|
|
449
|
+
// could not get out of.
|
|
450
|
+
constexpr int kFallbackTimeoutMs = 100;
|
|
451
|
+
const int receive_timeout_ms = is_valid_socket(interrupt_fd) ? -1 : kFallbackTimeoutMs;
|
|
452
|
+
|
|
453
|
+
// A single failed receive is not fatal (a signal, a transient ICMP error), but a
|
|
454
|
+
// socket that is genuinely dead fails instantly every time — without a bound the
|
|
455
|
+
// loop below degenerates into a busy spin that never ends. Give up after a short
|
|
456
|
+
// run of back-to-back failures; the old blocking loop bailed on the first one.
|
|
457
|
+
constexpr int kMaxConsecutiveErrors = 10;
|
|
458
|
+
int consecutive_errors = 0;
|
|
459
|
+
|
|
433
460
|
while (running_.load()) {
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
461
|
+
Address sender;
|
|
462
|
+
bool receive_failed = false;
|
|
463
|
+
std::vector<uint8_t> packet = librats::receive_udp_data(
|
|
464
|
+
multicast_socket_, 4096, sender, receive_timeout_ms, interrupt_fd, &receive_failed);
|
|
465
|
+
|
|
466
|
+
if (receive_failed) {
|
|
467
|
+
if (++consecutive_errors >= kMaxConsecutiveErrors) {
|
|
468
|
+
if (running_.load()) {
|
|
469
|
+
LOG_MDNS_ERROR("mDNS receive failed " << consecutive_errors
|
|
470
|
+
<< " times in a row, stopping receiver loop");
|
|
471
|
+
}
|
|
472
|
+
break;
|
|
444
473
|
}
|
|
445
|
-
|
|
474
|
+
continue;
|
|
446
475
|
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
476
|
+
|
|
477
|
+
consecutive_errors = 0;
|
|
478
|
+
|
|
479
|
+
if (packet.empty()) {
|
|
480
|
+
// Either the wait was interrupted or (in the degraded fallback) it timed
|
|
481
|
+
// out. Consume the wakeup byte — an unread one keeps the pipe readable and
|
|
482
|
+
// would turn the next wait into a spin — then re-check running_.
|
|
483
|
+
receiver_wakeup_.drain();
|
|
484
|
+
continue;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
std::string sender_ip = sender.ip.to_string();
|
|
488
|
+
|
|
452
489
|
// Ignore packets from ourselves
|
|
453
|
-
if (
|
|
490
|
+
if (sender_ip == local_ip_address_) {
|
|
454
491
|
continue;
|
|
455
492
|
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
std::vector<uint8_t> packet(buffer.begin(), buffer.begin() + received);
|
|
459
|
-
handle_received_packet(packet, std::string(sender_ip));
|
|
493
|
+
|
|
494
|
+
handle_received_packet(packet, sender_ip);
|
|
460
495
|
}
|
|
461
|
-
|
|
496
|
+
|
|
462
497
|
LOG_MDNS_DEBUG("mDNS receiver loop ended");
|
|
463
498
|
}
|
|
464
499
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
-
#include "socket.h"
|
|
4
|
-
#include "
|
|
3
|
+
#include "librats/core/socket.h"
|
|
4
|
+
#include "librats/core/wakeup_pipe.h"
|
|
5
5
|
#include <string>
|
|
6
6
|
#include <vector>
|
|
7
7
|
#include <memory>
|
|
@@ -17,11 +17,6 @@
|
|
|
17
17
|
|
|
18
18
|
namespace librats {
|
|
19
19
|
|
|
20
|
-
#define LOG_MDNS_DEBUG(message) LOG_DEBUG("mdns", message)
|
|
21
|
-
#define LOG_MDNS_INFO(message) LOG_INFO("mdns", message)
|
|
22
|
-
#define LOG_MDNS_WARN(message) LOG_WARN("mdns", message)
|
|
23
|
-
#define LOG_MDNS_ERROR(message) LOG_ERROR("mdns", message)
|
|
24
|
-
|
|
25
20
|
// mDNS protocol constants
|
|
26
21
|
const uint16_t MDNS_PORT = 5353;
|
|
27
22
|
const std::string MDNS_MULTICAST_IPv4 = "224.0.0.251";
|
|
@@ -176,7 +171,13 @@ private:
|
|
|
176
171
|
std::thread receiver_thread_;
|
|
177
172
|
std::thread announcer_thread_;
|
|
178
173
|
std::thread querier_thread_;
|
|
179
|
-
|
|
174
|
+
|
|
175
|
+
/// Lets stop() interrupt the receiver's blocking wait. Without it the loop
|
|
176
|
+
/// would have to poll the multicast socket on a timeout just to notice that
|
|
177
|
+
/// running_ went false, which costs a wakeup per interval forever — on a
|
|
178
|
+
/// client that is otherwise completely idle, that is the only work it does.
|
|
179
|
+
WakeupPipe receiver_wakeup_;
|
|
180
|
+
|
|
180
181
|
// Conditional variables for immediate shutdown
|
|
181
182
|
std::condition_variable shutdown_cv_;
|
|
182
183
|
std::mutex shutdown_mutex_;
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* @brief NAT-PMP (RFC 6886) client implementation
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
#include "natpmp.h"
|
|
7
|
-
#include "network_utils.h"
|
|
8
|
-
#include "logger.h"
|
|
6
|
+
#include "librats/nat/natpmp.h"
|
|
7
|
+
#include "librats/util/network_utils.h"
|
|
8
|
+
#include "librats/util/logger.h"
|
|
9
9
|
|
|
10
10
|
#include <cstring>
|
|
11
11
|
|
|
@@ -174,14 +174,15 @@ bool NatPmpClient::ensure_gateway() {
|
|
|
174
174
|
socket_t sock = create_udp_socket(0, "", AddressFamily::IPv4);
|
|
175
175
|
if (!is_valid_socket(sock)) continue;
|
|
176
176
|
|
|
177
|
+
const auto gw_ip = IpAddress::parse(gw); // gateway is a numeric literal; parse once, compare by bytes
|
|
177
178
|
std::vector<uint8_t> req = { NATPMP_VERSION, OP_EXTERNAL_IP };
|
|
178
179
|
bool answered = false;
|
|
179
180
|
for (int timeout : kRetryTimeouts) {
|
|
180
181
|
if (stop_requested_.load()) { close_socket(sock); return false; }
|
|
181
182
|
if (send_udp_data(sock, req, gw, NATPMP_PORT, AddressFamily::IPv4) < 0) break;
|
|
182
|
-
|
|
183
|
+
Address from;
|
|
183
184
|
auto resp = receive_udp_data(sock, 64, from, timeout, wakeup_.fd());
|
|
184
|
-
if (resp.size() >= 12 && from.ip ==
|
|
185
|
+
if (resp.size() >= 12 && gw_ip && from.ip == *gw_ip && resp[0] == NATPMP_VERSION &&
|
|
185
186
|
resp[1] == (OP_EXTERNAL_IP | OP_RESPONSE_BIT)) {
|
|
186
187
|
uint16_t result = get_u16(&resp[2]);
|
|
187
188
|
if (result == 0) {
|
|
@@ -224,14 +225,15 @@ bool NatPmpClient::request_external_ip(socket_t sock) {
|
|
|
224
225
|
gw = gateway_;
|
|
225
226
|
}
|
|
226
227
|
if (gw.empty()) return false;
|
|
228
|
+
const auto gw_ip = IpAddress::parse(gw); // numeric literal; parse once, compare by bytes
|
|
227
229
|
|
|
228
230
|
std::vector<uint8_t> req = { NATPMP_VERSION, OP_EXTERNAL_IP };
|
|
229
231
|
for (int timeout : kRetryTimeouts) {
|
|
230
232
|
if (stop_requested_.load()) return false;
|
|
231
233
|
if (send_udp_data(sock, req, gw, NATPMP_PORT, AddressFamily::IPv4) < 0) return false;
|
|
232
|
-
|
|
234
|
+
Address from;
|
|
233
235
|
auto resp = receive_udp_data(sock, 64, from, timeout, wakeup_.fd());
|
|
234
|
-
if (resp.size() >= 12 && from.ip ==
|
|
236
|
+
if (resp.size() >= 12 && gw_ip && from.ip == *gw_ip && resp[0] == NATPMP_VERSION &&
|
|
235
237
|
resp[1] == (OP_EXTERNAL_IP | OP_RESPONSE_BIT) && get_u16(&resp[2]) == 0) {
|
|
236
238
|
char ip[INET_ADDRSTRLEN];
|
|
237
239
|
struct in_addr addr;
|
|
@@ -253,6 +255,7 @@ bool NatPmpClient::send_map_request(socket_t sock, Mapping& m, bool remove) {
|
|
|
253
255
|
gw = gateway_;
|
|
254
256
|
}
|
|
255
257
|
if (gw.empty()) return false;
|
|
258
|
+
const auto gw_ip = IpAddress::parse(gw); // numeric literal; parse once, compare by bytes
|
|
256
259
|
|
|
257
260
|
const uint32_t lifetime = remove ? 0 : lease_duration_;
|
|
258
261
|
const uint16_t requested_external = remove ? 0 : m.external_port;
|
|
@@ -291,9 +294,9 @@ bool NatPmpClient::send_map_request(socket_t sock, Mapping& m, bool remove) {
|
|
|
291
294
|
if (stop_requested_.load()) return false;
|
|
292
295
|
if (send_udp_data(sock, req, gw, NATPMP_PORT, AddressFamily::IPv4) < 0) return false;
|
|
293
296
|
|
|
294
|
-
|
|
297
|
+
Address from;
|
|
295
298
|
auto resp = receive_udp_data(sock, 64, from, timeout, wakeup_.fd());
|
|
296
|
-
if (resp.size() < 16 || from.ip !=
|
|
299
|
+
if (resp.size() < 16 || !gw_ip || from.ip != *gw_ip) continue;
|
|
297
300
|
if (resp[0] != NATPMP_VERSION || resp[1] != expected_opcode) continue;
|
|
298
301
|
|
|
299
302
|
uint16_t result = get_u16(&resp[2]);
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
* @endcode
|
|
25
25
|
*/
|
|
26
26
|
|
|
27
|
-
#include "port_mapping.h"
|
|
28
|
-
#include "socket.h"
|
|
29
|
-
#include "wakeup_pipe.h"
|
|
27
|
+
#include "librats/nat/port_mapping.h"
|
|
28
|
+
#include "librats/core/socket.h"
|
|
29
|
+
#include "librats/core/wakeup_pipe.h"
|
|
30
30
|
|
|
31
31
|
#include <atomic>
|
|
32
32
|
#include <condition_variable>
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
* home router to forward an external (WAN) port to a local (LAN) port so that
|
|
9
9
|
* inbound peer connections can reach a host behind NAT. They share the small set
|
|
10
10
|
* of vocabulary types defined here: the transport protocol of the mapping, which
|
|
11
|
-
* backend produced a result, and the result/callback shape
|
|
11
|
+
* backend produced a result, and the result/callback shape PortMappingService
|
|
12
|
+
* consumes.
|
|
12
13
|
*/
|
|
13
14
|
|
|
14
15
|
#include <cstdint>
|
|
@@ -63,7 +64,7 @@ struct PortMapResult {
|
|
|
63
64
|
using PortMapCallback = std::function<void(const PortMapResult&)>;
|
|
64
65
|
|
|
65
66
|
/**
|
|
66
|
-
* Configuration for
|
|
67
|
+
* Configuration for automatic port forwarding (see PortMappingService).
|
|
67
68
|
*
|
|
68
69
|
* Both backends run in parallel by default; whichever the router supports
|
|
69
70
|
* succeeds. Disabling one (or all) of them is a matter of flipping a flag.
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* Implements RFC 5389 - STUN protocol for NAT traversal.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
#include "stun.h"
|
|
9
|
-
#include "logger.h"
|
|
10
|
-
#include "network_utils.h"
|
|
8
|
+
#include "librats/nat/stun.h"
|
|
9
|
+
#include "librats/util/logger.h"
|
|
10
|
+
#include "librats/util/network_utils.h"
|
|
11
11
|
#include <cstring>
|
|
12
12
|
#include <algorithm>
|
|
13
13
|
#include <chrono>
|
|
@@ -1057,7 +1057,7 @@ std::optional<StunMessage> StunClient::send_request(socket_t socket,
|
|
|
1057
1057
|
|
|
1058
1058
|
// Wait for response with current RTO
|
|
1059
1059
|
int wait_time = (std::min)(rto, timeout_ms - total_time);
|
|
1060
|
-
|
|
1060
|
+
Address sender;
|
|
1061
1061
|
|
|
1062
1062
|
auto response_data = receive_udp_data(socket, STUN_MAX_MESSAGE_SIZE, sender, wait_time);
|
|
1063
1063
|
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* @brief UPnP IGD port mapping client implementation
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
#include "upnp.h"
|
|
7
|
-
#include "socket.h"
|
|
8
|
-
#include "logger.h"
|
|
6
|
+
#include "librats/nat/upnp.h"
|
|
7
|
+
#include "librats/core/socket.h"
|
|
8
|
+
#include "librats/util/logger.h"
|
|
9
9
|
|
|
10
10
|
#include <cstring>
|
|
11
11
|
#include <cstdio>
|
|
@@ -313,7 +313,7 @@ bool UpnpClient::discover_device(Device& out) {
|
|
|
313
313
|
|
|
314
314
|
auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(2);
|
|
315
315
|
while (std::chrono::steady_clock::now() < deadline && !stop_requested_.load()) {
|
|
316
|
-
|
|
316
|
+
Address from;
|
|
317
317
|
auto resp = receive_udp_data(sock, 2048, from, 1000, wakeup_.fd());
|
|
318
318
|
if (resp.empty()) continue;
|
|
319
319
|
|
|
@@ -334,8 +334,8 @@ bool UpnpClient::discover_device(Device& out) {
|
|
|
334
334
|
if (std::find(tried.begin(), tried.end(), location) != tried.end()) continue;
|
|
335
335
|
tried.push_back(location);
|
|
336
336
|
|
|
337
|
-
std::string local_ip = local_ip_for_destination(from.ip, from.port);
|
|
338
|
-
LOG_UPNP_DEBUG("SSDP reply from " << from.ip << " location=" << location);
|
|
337
|
+
std::string local_ip = local_ip_for_destination(from.ip.to_string(), from.port);
|
|
338
|
+
LOG_UPNP_DEBUG("SSDP reply from " << from.ip.to_string() << " location=" << location);
|
|
339
339
|
if (fetch_description(location, local_ip, out)) {
|
|
340
340
|
found = true;
|
|
341
341
|
break;
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
* external XML/HTTP libraries) using librats' own socket primitives.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
#include "port_mapping.h"
|
|
22
|
-
#include "wakeup_pipe.h"
|
|
21
|
+
#include "librats/nat/port_mapping.h"
|
|
22
|
+
#include "librats/core/wakeup_pipe.h"
|
|
23
23
|
|
|
24
24
|
#include <atomic>
|
|
25
25
|
#include <condition_variable>
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file circuit_service.h
|
|
5
|
+
* @brief Turning a relayed byte stream into a peer connection — the capability a
|
|
6
|
+
* relay module needs and PeerNetwork deliberately does not offer.
|
|
7
|
+
*
|
|
8
|
+
* A relay module speaks a protocol (who forwards what to whom) and owns the byte
|
|
9
|
+
* stream that comes out of it (transport/relay_link.h). What it cannot do on its
|
|
10
|
+
* own is the one remaining step: making that stream a Connection, so the ordinary
|
|
11
|
+
* Noise handshake, framing, identify and peer table all run over it and the peer
|
|
12
|
+
* at the far end becomes an ordinary peer. That step needs the reactor pool, which
|
|
13
|
+
* a Subsystem has no business holding.
|
|
14
|
+
*
|
|
15
|
+
* So this is the narrow escape hatch, published by the Node in its ServiceRegistry
|
|
16
|
+
* next to DialService, and resolved by whoever needs it:
|
|
17
|
+
*
|
|
18
|
+
* if (auto* circuits = ctx.services.get<CircuitService>())
|
|
19
|
+
* auto route = circuits->adopt_circuit(relay_id, std::move(link),
|
|
20
|
+
* ConnRole::Outbound, false);
|
|
21
|
+
*
|
|
22
|
+
* ── One thread, chosen for you ──────────────────────────────────────────────
|
|
23
|
+
* The node places the circuit on the reactor that owns the CARRIER's connection,
|
|
24
|
+
* and that is the whole reason this call exists rather than a bare "adopt this
|
|
25
|
+
* link somewhere". Every byte of a circuit arrives on the carrier's connection and
|
|
26
|
+
* leaves through it, so putting the two on one thread means the entire relayed
|
|
27
|
+
* path is handled without a lock, a queue or a hand-off — the same shared-nothing
|
|
28
|
+
* property every other connection has. Any other placement would move bytes
|
|
29
|
+
* between reactor threads twice per message.
|
|
30
|
+
*
|
|
31
|
+
* The route comes back synchronously (the ConnId is reserved before the adoption
|
|
32
|
+
* is posted, exactly as Reactor::connect does), so the caller can wake and close
|
|
33
|
+
* the circuit from the moment it asks for one.
|
|
34
|
+
*
|
|
35
|
+
* ── What is deliberately NOT here ───────────────────────────────────────────
|
|
36
|
+
* Nothing about relaying: no relay selection, no protocol, no policy about when a
|
|
37
|
+
* circuit is worth opening. Those belong to the module. This interface would serve
|
|
38
|
+
* any transport that arrives from outside the reactor pool.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
#include "librats/core/types.h"
|
|
42
|
+
#include "librats/peer/peer_id.h"
|
|
43
|
+
#include "librats/peer/peer_table.h" // PeerRoute
|
|
44
|
+
#include "librats/transport/link.h"
|
|
45
|
+
|
|
46
|
+
#include <cstdint>
|
|
47
|
+
#include <memory>
|
|
48
|
+
#include <optional>
|
|
49
|
+
|
|
50
|
+
namespace librats {
|
|
51
|
+
|
|
52
|
+
class CircuitService {
|
|
53
|
+
public:
|
|
54
|
+
virtual ~CircuitService() = default;
|
|
55
|
+
|
|
56
|
+
/// Adopt `link` as a connection carried by the peer `carrier`, on the reactor
|
|
57
|
+
/// that owns the carrier's own connection.
|
|
58
|
+
///
|
|
59
|
+
/// @param role Outbound for a circuit we opened, Inbound for one opened to
|
|
60
|
+
/// us. It is what the secure handshake and the peer table's
|
|
61
|
+
/// duplicate resolution read, so it must say who asked.
|
|
62
|
+
/// @param connected whether the far end is already there. An inbound circuit is
|
|
63
|
+
/// (the opener would not have sent it otherwise); an outbound
|
|
64
|
+
/// one is not until its acceptance arrives, and until then the
|
|
65
|
+
/// connection waits in Connecting for a PollOut.
|
|
66
|
+
/// @return the new connection's route, or nullopt when the carrier is no longer
|
|
67
|
+
/// a peer, or when an inbound circuit would push this node past its peer
|
|
68
|
+
/// limit. Nothing is started in that case and `link` is released.
|
|
69
|
+
virtual std::optional<PeerRoute> adopt_circuit(const PeerId& carrier,
|
|
70
|
+
std::unique_ptr<Link> link,
|
|
71
|
+
ConnRole role, bool connected) = 0;
|
|
72
|
+
|
|
73
|
+
/// Deliver poll-equivalent events (PollIn / PollOut / PollErr, see
|
|
74
|
+
/// core/io_poller.h) to a circuit connection — the events a socket-backed link
|
|
75
|
+
/// would have got from the poller. Thread-safe, and a no-op for a route that is
|
|
76
|
+
/// already gone.
|
|
77
|
+
virtual void wake_circuit(PeerRoute route, uint32_t events) = 0;
|
|
78
|
+
|
|
79
|
+
/// Tear a circuit connection down. Thread-safe; a no-op for a route that is
|
|
80
|
+
/// already gone.
|
|
81
|
+
virtual void close_circuit(PeerRoute route, CloseReason reason) = 0;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
} // namespace librats
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file config.h
|
|
5
|
+
* @brief Node construction options.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#include "librats/util/rats_export.h"
|
|
9
|
+
#include "librats/core/types.h" // TransportKind
|
|
10
|
+
|
|
11
|
+
#include <cstdint>
|
|
12
|
+
#include <string>
|
|
13
|
+
|
|
14
|
+
namespace librats {
|
|
15
|
+
|
|
16
|
+
struct RATS_API NodeConfig {
|
|
17
|
+
/// Listen port for inbound peers. 0 picks an ephemeral port. Ignored if
|
|
18
|
+
/// enable_listen is false (client-only node). Both transports use this same
|
|
19
|
+
/// port, so one advertised address is dialable over either.
|
|
20
|
+
uint16_t listen_port = 0;
|
|
21
|
+
bool enable_listen = true;
|
|
22
|
+
|
|
23
|
+
// ── Transports ──────────────────────────────────────────────────────────
|
|
24
|
+
//
|
|
25
|
+
// TCP and UDP are equal citizens here: identical framing, identical Noise
|
|
26
|
+
// handshake, identical guarantees. They differ only in how the ordered,
|
|
27
|
+
// reliable byte stream underneath is obtained — the kernel's TCP stack, or
|
|
28
|
+
// the library's own reliability layer over datagrams (transport/udp_stream.h).
|
|
29
|
+
// A node normally offers both and lets each dial pick.
|
|
30
|
+
|
|
31
|
+
/// Accept and dial over TCP.
|
|
32
|
+
bool enable_tcp = true;
|
|
33
|
+
/// Accept and dial over the datagram transport. Also gives a dial-only node a
|
|
34
|
+
/// single UDP socket to dial from, which is what keeps one NAT mapping open
|
|
35
|
+
/// for every peer instead of one per peer.
|
|
36
|
+
bool enable_udp = true;
|
|
37
|
+
|
|
38
|
+
/// Which transport a dial tries first.
|
|
39
|
+
///
|
|
40
|
+
/// UDP is the default because it is the better fit for peer-to-peer: every
|
|
41
|
+
/// peer shares one socket and therefore one NAT mapping, the port a peer sees
|
|
42
|
+
/// us send from is the port it can dial back, which is what makes hole
|
|
43
|
+
/// punching possible at all, and no middlebox holds per-connection state that
|
|
44
|
+
/// can be exhausted or timed out from under us. TCP remains a first-class
|
|
45
|
+
/// equal, and is what the fallback below exists for — some networks block or
|
|
46
|
+
/// throttle UDP outright.
|
|
47
|
+
TransportKind preferred_transport = TransportKind::Udp;
|
|
48
|
+
|
|
49
|
+
/// How long the preferred transport dials alone before the other one is
|
|
50
|
+
/// raced alongside it. The first to complete its handshake wins and the loser
|
|
51
|
+
/// is dropped, so a UDP-blocking network costs this delay rather than a failed
|
|
52
|
+
/// connection. 0 disables the fallback: only the preferred transport is tried.
|
|
53
|
+
uint32_t transport_fallback_ms = 1200;
|
|
54
|
+
|
|
55
|
+
/// Bytes a peer's send queue may hold before the peer is dropped as a slow
|
|
56
|
+
/// consumer. 0 uses the library default (8 MiB).
|
|
57
|
+
///
|
|
58
|
+
/// A quarter of this is the mark at which send() starts answering "no room"
|
|
59
|
+
/// and on_peer_writable is what says the room is back — so lowering it makes
|
|
60
|
+
/// an application feel backpressure sooner, and raising it lets a bursty one
|
|
61
|
+
/// buffer more before anything is said. The two move together on purpose:
|
|
62
|
+
/// a warning that arrives at the same moment as the disconnection is no
|
|
63
|
+
/// warning at all.
|
|
64
|
+
size_t send_queue_limit = 0;
|
|
65
|
+
|
|
66
|
+
/// Interface to bind the listener to. The address family is derived from it:
|
|
67
|
+
/// - "" or "::" → dual-stack wildcard: reachable over both IPv6 and IPv4
|
|
68
|
+
/// (IPv4-mapped) on all interfaces. This is the default.
|
|
69
|
+
/// - "0.0.0.0" → IPv4 on all interfaces.
|
|
70
|
+
/// - an IPv6 literal → IPv6-only, that interface (e.g. "::1" for v6 loopback).
|
|
71
|
+
/// - an IPv4 literal → IPv4, that interface (e.g. "127.0.0.1" for v4 loopback).
|
|
72
|
+
/// Bare IPv6 literals are written without brackets here; peer endpoints rendered
|
|
73
|
+
/// as text use bracketed "[ip]:port" form (see core/address.h).
|
|
74
|
+
std::string bind_address = "";
|
|
75
|
+
|
|
76
|
+
/// Number of reactor threads. 1 is plenty for thousands of peers; larger
|
|
77
|
+
/// pools shard outbound connections across cores.
|
|
78
|
+
size_t reactor_threads = 1;
|
|
79
|
+
|
|
80
|
+
/// Maximum number of established peers. 0 means unlimited. The limit guards
|
|
81
|
+
/// inbound connections (a flood is refused at accept, before any handshake);
|
|
82
|
+
/// outbound dials we initiate are always honored. Runtime-adjustable via
|
|
83
|
+
/// Node::set_max_peers().
|
|
84
|
+
size_t max_peers = 0;
|
|
85
|
+
|
|
86
|
+
/// Secure channel to use for peer connections.
|
|
87
|
+
enum class Security { Noise, Plaintext };
|
|
88
|
+
Security security = Security::Noise;
|
|
89
|
+
|
|
90
|
+
/// Application protocol identity, bound into the Noise handshake prologue, so
|
|
91
|
+
/// two nodes whose protocol differs cannot complete a handshake — a cheap,
|
|
92
|
+
/// cryptographically-enforced way to keep separate apps (or app versions)
|
|
93
|
+
/// from cross-connecting. An opaque string compared for exact equality; by
|
|
94
|
+
/// convention "<name>/<version>". Both peers must match. (Under Plaintext it
|
|
95
|
+
/// is still checked, but not cryptographically bound — see PlaintextSecurity.)
|
|
96
|
+
std::string protocol = "librats/1.0";
|
|
97
|
+
|
|
98
|
+
/// Directory for persistent state. Empty = ephemeral (a fresh random
|
|
99
|
+
/// identity each run). When set, the node's Noise keypair is loaded from /
|
|
100
|
+
/// saved to "<data_dir>/identity.key", giving a stable PeerId across restarts.
|
|
101
|
+
std::string data_dir = "";
|
|
102
|
+
|
|
103
|
+
/// Watch the host for network configuration changes (interface up/down, IP
|
|
104
|
+
/// add/remove, route flip, wake-from-sleep) and publish NetworkChanged on the
|
|
105
|
+
/// node's EventBus so subsystems can renew port mappings, re-run STUN and
|
|
106
|
+
/// re-announce. Costs one mostly-idle monitor thread. See node/host_events.h.
|
|
107
|
+
bool enable_network_monitor = true;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
} // namespace librats
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file dial_service.h
|
|
5
|
+
* @brief Dialing a specific endpoint over a specific wire — the capability a
|
|
6
|
+
* NAT-traversal module needs and the ordinary connect() cannot express.
|
|
7
|
+
*
|
|
8
|
+
* PeerNetwork::connect(Address) is deliberately opinionated: it hands the target to
|
|
9
|
+
* the Dialer, which picks a transport, races the other one in after the fallback
|
|
10
|
+
* delay, and remembers what it learned for next time (see node/dialer.h). That is
|
|
11
|
+
* exactly right for "connect me to this peer" and exactly wrong for a hole punch,
|
|
12
|
+
* which needs three things the race cannot give:
|
|
13
|
+
*
|
|
14
|
+
* - the datagram wire and nothing else. A punch is only possible on the shared
|
|
15
|
+
* UDP socket; racing TCP alongside it spends a connect attempt on a path that
|
|
16
|
+
* a NAT will refuse by construction.
|
|
17
|
+
* - a dial that starts NOW, at a moment agreed with the peer. A punch works
|
|
18
|
+
* because two Syns cross mid-path; a fallback delay measured from our own clock
|
|
19
|
+
* has nothing to do with that instant.
|
|
20
|
+
* - a different retry shape (see DialProfile) — dense probes rather than a long
|
|
21
|
+
* patient tail, because the early Syns are *expected* to die on the peer's NAT.
|
|
22
|
+
*
|
|
23
|
+
* So this is the narrow escape hatch, published by the Node in its ServiceRegistry
|
|
24
|
+
* and resolved by whoever needs it:
|
|
25
|
+
*
|
|
26
|
+
* if (auto* dial = ctx.services.get<DialService>())
|
|
27
|
+
* dial->dial_direct(addr, TransportKind::Udp, DialProfile::punch());
|
|
28
|
+
*
|
|
29
|
+
* It is deliberately *not* on PeerNetwork: every subsystem sees that interface, and
|
|
30
|
+
* "dial exactly this, exactly this way" is a capability one module needs rather than
|
|
31
|
+
* a contract all of them should have. Everything else about the resulting connection
|
|
32
|
+
* is ordinary — the same handshake, the same identify, the same duplicate resolution
|
|
33
|
+
* in PeerTable if the peer dialed us back at the same moment.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
#include "librats/core/address.h"
|
|
37
|
+
#include "librats/core/types.h"
|
|
38
|
+
|
|
39
|
+
namespace librats {
|
|
40
|
+
|
|
41
|
+
class DialService {
|
|
42
|
+
public:
|
|
43
|
+
virtual ~DialService() = default;
|
|
44
|
+
|
|
45
|
+
/// Start exactly one dial to `addr` over `kind`, bypassing the transport race.
|
|
46
|
+
/// Non-blocking; the outcome surfaces through the node's ordinary peer-connected
|
|
47
|
+
/// event. Returns false when the node cannot carry that transport at all (no
|
|
48
|
+
/// datagram socket, or an address family the one socket cannot reach), in which
|
|
49
|
+
/// case nothing was started and no failure event will follow.
|
|
50
|
+
virtual bool dial_direct(const Address& addr, TransportKind kind,
|
|
51
|
+
const DialProfile& profile) = 0;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
} // namespace librats
|