librats 1.0.2 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +145 -331
- package/binding.gyp +16 -3
- package/lib/index.d.ts +288 -696
- package/lib/index.js +407 -44
- package/native-src/3rdparty/android/ifaddrs-android.c +1 -0
- package/native-src/3rdparty/android/ifaddrs-android.h +1 -0
- package/native-src/CMakeLists.txt +404 -179
- package/native-src/LICENSE +1 -1
- package/native-src/src/librats/bindings/rats.cpp +762 -0
- package/native-src/src/librats/bindings/rats.h +380 -0
- package/native-src/src/librats/bittorrent/bencode.cpp +437 -0
- package/native-src/src/librats/bittorrent/bencode.h +176 -0
- package/native-src/src/librats/bittorrent/bitfield.cpp +97 -0
- package/native-src/src/librats/bittorrent/bitfield.h +76 -0
- package/native-src/src/librats/bittorrent/byte_io.h +58 -0
- package/native-src/src/librats/bittorrent/choker.cpp +25 -0
- package/native-src/src/librats/bittorrent/choker.h +46 -0
- package/native-src/src/librats/bittorrent/client.cpp +413 -0
- package/native-src/src/librats/bittorrent/client.h +227 -0
- package/native-src/src/librats/bittorrent/disk_io.cpp +209 -0
- package/native-src/src/librats/bittorrent/disk_io.h +150 -0
- package/native-src/src/librats/bittorrent/extensions.cpp +191 -0
- package/native-src/src/librats/bittorrent/extensions.h +94 -0
- package/native-src/src/librats/bittorrent/file_storage.cpp +77 -0
- package/native-src/src/librats/bittorrent/file_storage.h +79 -0
- package/native-src/src/librats/bittorrent/log.h +42 -0
- package/native-src/src/librats/bittorrent/magnet_uri.cpp +98 -0
- package/native-src/src/librats/bittorrent/magnet_uri.h +35 -0
- package/native-src/src/librats/bittorrent/peer_connection.cpp +502 -0
- package/native-src/src/librats/bittorrent/peer_connection.h +194 -0
- package/native-src/src/librats/bittorrent/peer_list.cpp +68 -0
- package/native-src/src/librats/bittorrent/peer_list.h +75 -0
- package/native-src/src/librats/bittorrent/piece_picker.cpp +352 -0
- package/native-src/src/librats/bittorrent/piece_picker.h +201 -0
- package/native-src/src/librats/bittorrent/reactor.cpp +97 -0
- package/native-src/src/librats/bittorrent/reactor.h +89 -0
- package/native-src/src/librats/bittorrent/resume_data.cpp +72 -0
- package/native-src/src/librats/bittorrent/resume_data.h +41 -0
- package/native-src/src/librats/bittorrent/store_buffer.cpp +48 -0
- package/native-src/src/librats/bittorrent/store_buffer.h +47 -0
- package/native-src/src/librats/bittorrent/torrent.cpp +870 -0
- package/native-src/src/librats/bittorrent/torrent.h +260 -0
- package/native-src/src/librats/bittorrent/torrent_creator.cpp +129 -0
- package/native-src/src/librats/bittorrent/torrent_creator.h +58 -0
- package/native-src/src/librats/bittorrent/torrent_info.cpp +314 -0
- package/native-src/src/librats/bittorrent/torrent_info.h +118 -0
- package/native-src/src/librats/bittorrent/tracker.cpp +374 -0
- package/native-src/src/librats/bittorrent/tracker.h +108 -0
- package/native-src/src/librats/bittorrent/types.cpp +206 -0
- package/native-src/src/librats/bittorrent/types.h +86 -0
- package/native-src/src/librats/core/address.cpp +35 -0
- package/native-src/src/librats/core/address.h +78 -0
- package/native-src/src/librats/core/bytes.h +69 -0
- package/native-src/src/librats/core/chained_send_buffer.cpp +172 -0
- package/native-src/src/librats/core/chained_send_buffer.h +183 -0
- package/native-src/src/librats/core/endpoint_parse.cpp +41 -0
- package/native-src/src/librats/core/endpoint_parse.h +31 -0
- package/native-src/src/librats/core/event_bus.h +70 -0
- package/native-src/src/librats/core/host_endpoint.h +56 -0
- package/native-src/src/{io_poller.cpp → librats/core/io_poller.cpp} +520 -65
- package/native-src/src/{io_poller.h → librats/core/io_poller.h} +12 -6
- package/native-src/src/librats/core/ip_address.cpp +120 -0
- package/native-src/src/librats/core/ip_address.h +109 -0
- package/native-src/src/librats/core/mpsc_queue.h +47 -0
- package/native-src/src/librats/core/notifier.h +74 -0
- package/native-src/src/librats/core/receive_buffer.cpp +219 -0
- package/native-src/src/librats/core/receive_buffer.h +171 -0
- package/native-src/src/librats/core/service_registry.h +58 -0
- package/native-src/src/{socket.cpp → librats/core/socket.cpp} +625 -118
- package/native-src/src/librats/core/socket.h +496 -0
- package/native-src/src/librats/core/timer_queue.h +105 -0
- package/native-src/src/librats/core/types.cpp +43 -0
- package/native-src/src/librats/core/types.h +103 -0
- package/native-src/src/librats/core/wakeup_pipe.h +83 -0
- package/native-src/src/{crypto → librats/crypto}/blake2_endian.h +21 -23
- package/native-src/src/{crypto → librats/crypto}/blake2b.c +34 -33
- package/native-src/src/{crypto → librats/crypto}/blake2b.h +7 -6
- package/native-src/src/{crypto → librats/crypto}/blake2s.c +55 -54
- package/native-src/src/{crypto → librats/crypto}/blake2s.h +13 -12
- package/native-src/src/{crypto → librats/crypto}/chacha.c +22 -21
- package/native-src/src/{crypto → librats/crypto}/chacha.h +14 -13
- package/native-src/src/{crypto → librats/crypto}/chachapoly.c +56 -56
- package/native-src/src/{crypto → librats/crypto}/chachapoly.h +24 -17
- package/native-src/src/{crc32.cpp → librats/crypto/crc32.cpp} +1 -1
- package/native-src/src/{crc32.h → librats/crypto/crc32.h} +3 -1
- package/native-src/src/{crypto → librats/crypto}/curve25519.c +6 -4
- package/native-src/src/{crypto → librats/crypto}/curve25519.h +6 -3
- package/native-src/src/librats/crypto/hkdf.c +266 -0
- package/native-src/src/{crypto → librats/crypto}/hkdf.h +19 -19
- package/native-src/src/{noise.cpp → librats/crypto/noise.cpp} +84 -73
- package/native-src/src/{noise.h → librats/crypto/noise.h} +18 -8
- package/native-src/src/{crypto → librats/crypto}/poly1305.c +47 -46
- package/native-src/src/librats/crypto/poly1305.h +37 -0
- package/native-src/src/{sha1.cpp → librats/crypto/sha1.cpp} +33 -1
- package/native-src/src/{sha1.h → librats/crypto/sha1.h} +14 -6
- package/native-src/src/{crypto → librats/crypto}/sha256.c +15 -14
- package/native-src/src/{crypto → librats/crypto}/sha256.h +8 -7
- package/native-src/src/{crypto → librats/crypto}/sha512.c +15 -14
- package/native-src/src/{crypto → librats/crypto}/sha512.h +8 -7
- package/native-src/src/librats/dht/announce.cpp +37 -0
- package/native-src/src/librats/dht/announce.h +41 -0
- package/native-src/src/librats/dht/bep42.cpp +109 -0
- package/native-src/src/librats/dht/bep42.h +48 -0
- package/native-src/src/librats/dht/dht.cpp +501 -0
- package/native-src/src/librats/dht/dht.h +119 -0
- package/native-src/src/librats/dht/dht_runner.cpp +103 -0
- package/native-src/src/librats/dht/dht_runner.h +71 -0
- package/native-src/src/librats/dht/dos_blocker.cpp +42 -0
- package/native-src/src/librats/dht/dos_blocker.h +47 -0
- package/native-src/src/librats/dht/find_peers.cpp +52 -0
- package/native-src/src/librats/dht/find_peers.h +73 -0
- package/native-src/src/librats/dht/id.h +167 -0
- package/native-src/src/{krpc.cpp → librats/dht/krpc.cpp} +32 -81
- package/native-src/src/{krpc.h → librats/dht/krpc.h} +19 -23
- package/native-src/src/librats/dht/log.h +38 -0
- package/native-src/src/librats/dht/node.cpp +473 -0
- package/native-src/src/librats/dht/node.h +164 -0
- package/native-src/src/librats/dht/node_entry.h +81 -0
- package/native-src/src/librats/dht/observer.h +72 -0
- package/native-src/src/librats/dht/persistence.cpp +90 -0
- package/native-src/src/librats/dht/persistence.h +32 -0
- package/native-src/src/librats/dht/routing_table.cpp +559 -0
- package/native-src/src/librats/dht/routing_table.h +185 -0
- package/native-src/src/librats/dht/rpc_manager.cpp +127 -0
- package/native-src/src/librats/dht/rpc_manager.h +77 -0
- package/native-src/src/librats/dht/storage.cpp +92 -0
- package/native-src/src/librats/dht/storage.h +74 -0
- package/native-src/src/librats/dht/transport.h +27 -0
- package/native-src/src/librats/dht/traversal.cpp +326 -0
- package/native-src/src/librats/dht/traversal.h +120 -0
- package/native-src/src/librats/dht/udp_transport.cpp +49 -0
- package/native-src/src/librats/dht/udp_transport.h +51 -0
- package/native-src/src/librats/mdns/log.h +22 -0
- package/native-src/src/{mdns.cpp → librats/mdns/mdns.cpp} +75 -40
- package/native-src/src/{mdns.h → librats/mdns/mdns.h} +9 -8
- package/native-src/src/{natpmp.cpp → librats/nat/natpmp.cpp} +12 -9
- package/native-src/src/{natpmp.h → librats/nat/natpmp.h} +3 -3
- package/native-src/src/{port_mapping.h → librats/nat/port_mapping.h} +3 -2
- package/native-src/src/{stun.cpp → librats/nat/stun.cpp} +4 -4
- package/native-src/src/{stun.h → librats/nat/stun.h} +1 -1
- package/native-src/src/{upnp.cpp → librats/nat/upnp.cpp} +6 -6
- package/native-src/src/{upnp.h → librats/nat/upnp.h} +2 -2
- package/native-src/src/librats/node/circuit_service.h +84 -0
- package/native-src/src/librats/node/config.h +110 -0
- package/native-src/src/librats/node/dial_service.h +54 -0
- package/native-src/src/librats/node/dialer.cpp +264 -0
- package/native-src/src/librats/node/dialer.h +188 -0
- package/native-src/src/librats/node/host_events.h +26 -0
- package/native-src/src/librats/node/identify.cpp +130 -0
- package/native-src/src/librats/node/identify.h +71 -0
- package/native-src/src/librats/node/nat_status.cpp +103 -0
- package/native-src/src/librats/node/nat_status.h +118 -0
- package/native-src/src/librats/node/node.cpp +865 -0
- package/native-src/src/librats/node/node.h +344 -0
- package/native-src/src/librats/node/node_context.h +33 -0
- package/native-src/src/librats/node/peer_network.h +91 -0
- package/native-src/src/librats/peer/peer.h +49 -0
- package/native-src/src/librats/peer/peer_book.cpp +181 -0
- package/native-src/src/librats/peer/peer_book.h +88 -0
- package/native-src/src/librats/peer/peer_id.cpp +72 -0
- package/native-src/src/librats/peer/peer_id.h +62 -0
- package/native-src/src/librats/peer/peer_info.h +37 -0
- package/native-src/src/librats/peer/peer_table.cpp +170 -0
- package/native-src/src/librats/peer/peer_table.h +148 -0
- package/native-src/src/librats/security/handshaker.h +66 -0
- package/native-src/src/librats/security/identity.h +43 -0
- package/native-src/src/librats/security/noise_security.cpp +122 -0
- package/native-src/src/librats/security/noise_security.h +37 -0
- package/native-src/src/librats/security/plaintext_security.h +106 -0
- package/native-src/src/librats/security/session.h +37 -0
- package/native-src/src/{storage.cpp → librats/storage/storage.cpp} +369 -522
- package/native-src/src/{storage.h → librats/storage/storage.h} +135 -299
- package/native-src/src/librats/subsystems/bittorrent.cpp +211 -0
- package/native-src/src/librats/subsystems/bittorrent.h +136 -0
- package/native-src/src/librats/subsystems/dht_discovery.cpp +202 -0
- package/native-src/src/librats/subsystems/dht_discovery.h +123 -0
- package/native-src/src/librats/subsystems/dht_service.h +36 -0
- package/native-src/src/librats/subsystems/file_transfer.cpp +972 -0
- package/native-src/src/librats/subsystems/file_transfer.h +367 -0
- package/native-src/src/librats/subsystems/hole_punch.cpp +605 -0
- package/native-src/src/librats/subsystems/hole_punch.h +290 -0
- package/native-src/src/librats/subsystems/hole_punch_service.h +38 -0
- package/native-src/src/librats/subsystems/mdns_discovery.cpp +66 -0
- package/native-src/src/librats/subsystems/mdns_discovery.h +55 -0
- package/native-src/src/librats/subsystems/message_json.cpp +112 -0
- package/native-src/src/librats/subsystems/message_json.h +88 -0
- package/native-src/src/librats/subsystems/peer_exchange.cpp +241 -0
- package/native-src/src/librats/subsystems/peer_exchange.h +136 -0
- package/native-src/src/librats/subsystems/ping_service.cpp +98 -0
- package/native-src/src/librats/subsystems/ping_service.h +66 -0
- package/native-src/src/librats/subsystems/port_mapping_service.cpp +192 -0
- package/native-src/src/librats/subsystems/port_mapping_service.h +84 -0
- package/native-src/src/librats/subsystems/pubsub.cpp +567 -0
- package/native-src/src/librats/subsystems/pubsub.h +175 -0
- package/native-src/src/librats/subsystems/reconnection.cpp +239 -0
- package/native-src/src/librats/subsystems/reconnection.h +126 -0
- package/native-src/src/librats/subsystems/relay.cpp +1142 -0
- package/native-src/src/librats/subsystems/relay.h +211 -0
- package/native-src/src/librats/subsystems/relay_service.h +46 -0
- package/native-src/src/librats/transport/connection.cpp +343 -0
- package/native-src/src/librats/transport/connection.h +283 -0
- package/native-src/src/librats/transport/link.h +96 -0
- package/native-src/src/librats/transport/reactor.cpp +588 -0
- package/native-src/src/librats/transport/reactor.h +262 -0
- package/native-src/src/librats/transport/reactor_pool.h +81 -0
- package/native-src/src/librats/transport/relay_link.cpp +208 -0
- package/native-src/src/librats/transport/relay_link.h +303 -0
- package/native-src/src/librats/transport/tcp_link.cpp +49 -0
- package/native-src/src/librats/transport/tcp_link.h +43 -0
- package/native-src/src/librats/transport/udp_mux.cpp +617 -0
- package/native-src/src/librats/transport/udp_mux.h +363 -0
- package/native-src/src/librats/transport/udp_packet.cpp +121 -0
- package/native-src/src/librats/transport/udp_packet.h +190 -0
- package/native-src/src/librats/transport/udp_stream.cpp +1194 -0
- package/native-src/src/librats/transport/udp_stream.h +614 -0
- package/native-src/src/librats/util/features.h.in +51 -0
- package/native-src/src/{fs.cpp → librats/util/fs.cpp} +51 -3
- package/native-src/src/librats/util/fs.h +136 -0
- package/native-src/src/librats/util/json.cpp +1002 -0
- package/native-src/src/librats/util/json.h +444 -0
- package/native-src/src/{logger.cpp → librats/util/logger.cpp} +1 -1
- package/native-src/src/{logger.h → librats/util/logger.h} +43 -31
- package/native-src/src/{network_monitor.cpp → librats/util/network_monitor.cpp} +12 -4
- package/native-src/src/{network_monitor.h → librats/util/network_monitor.h} +2 -1
- package/native-src/src/{network_utils.cpp → librats/util/network_utils.cpp} +38 -23
- package/native-src/src/{network_utils.h → librats/util/network_utils.h} +15 -8
- package/native-src/src/{os.cpp → librats/util/os.cpp} +48 -18
- package/native-src/src/librats/util/rats_export.h +69 -0
- package/native-src/src/{version.cpp → librats/util/version.cpp} +2 -2
- package/native-src/src/{version.h.in → librats/util/version.h.in} +1 -1
- package/native-src/src/librats/wire/frame.cpp +76 -0
- package/native-src/src/librats/wire/frame.h +111 -0
- package/native-src/src/librats/wire/message_router.cpp +45 -0
- package/native-src/src/librats/wire/message_router.h +47 -0
- package/package.json +5 -4
- package/scripts/build-librats.js +1 -0
- package/scripts/postinstall.js +3 -3
- package/scripts/prepare-package.js +4 -4
- package/scripts/verify-installation.js +63 -105
- package/src/librats_node.cpp +1067 -1323
- package/native-src/src/bencode.cpp +0 -485
- package/native-src/src/bencode.h +0 -145
- package/native-src/src/bittorrent.cpp +0 -14
- package/native-src/src/bittorrent.h +0 -74
- package/native-src/src/bt_bitfield.cpp +0 -372
- package/native-src/src/bt_bitfield.h +0 -316
- package/native-src/src/bt_choker.cpp +0 -228
- package/native-src/src/bt_choker.h +0 -147
- package/native-src/src/bt_client.cpp +0 -1047
- package/native-src/src/bt_client.h +0 -445
- package/native-src/src/bt_create_torrent.cpp +0 -677
- package/native-src/src/bt_create_torrent.h +0 -473
- package/native-src/src/bt_extension.cpp +0 -469
- package/native-src/src/bt_extension.h +0 -309
- package/native-src/src/bt_file_storage.cpp +0 -261
- package/native-src/src/bt_file_storage.h +0 -298
- package/native-src/src/bt_handshake.cpp +0 -134
- package/native-src/src/bt_handshake.h +0 -157
- package/native-src/src/bt_messages.cpp +0 -364
- package/native-src/src/bt_messages.h +0 -324
- package/native-src/src/bt_network.cpp +0 -1007
- package/native-src/src/bt_network.h +0 -417
- package/native-src/src/bt_peer_connection.cpp +0 -742
- package/native-src/src/bt_peer_connection.h +0 -592
- package/native-src/src/bt_piece_picker.cpp +0 -786
- package/native-src/src/bt_piece_picker.h +0 -473
- package/native-src/src/bt_resume_data.cpp +0 -410
- package/native-src/src/bt_resume_data.h +0 -249
- package/native-src/src/bt_torrent.cpp +0 -2120
- package/native-src/src/bt_torrent.h +0 -641
- package/native-src/src/bt_torrent_info.cpp +0 -659
- package/native-src/src/bt_torrent_info.h +0 -418
- package/native-src/src/bt_types.h +0 -621
- package/native-src/src/chained_send_buffer.cpp +0 -75
- package/native-src/src/chained_send_buffer.h +0 -137
- package/native-src/src/crypto/hkdf.c +0 -266
- package/native-src/src/crypto/poly1305.h +0 -36
- package/native-src/src/dht.cpp +0 -3311
- package/native-src/src/dht.h +0 -717
- package/native-src/src/disk_io.cpp +0 -632
- package/native-src/src/disk_io.h +0 -315
- package/native-src/src/file_transfer.cpp +0 -1415
- package/native-src/src/file_transfer.h +0 -286
- package/native-src/src/fs.h +0 -108
- package/native-src/src/gossipsub.cpp +0 -1139
- package/native-src/src/gossipsub.h +0 -403
- package/native-src/src/ice.cpp +0 -893
- package/native-src/src/ice.h +0 -559
- package/native-src/src/json.hpp +0 -25526
- package/native-src/src/librats.cpp +0 -2378
- package/native-src/src/librats.h +0 -2324
- package/native-src/src/librats_bittorrent.cpp +0 -601
- package/native-src/src/librats_c.cpp +0 -1557
- package/native-src/src/librats_c.h +0 -323
- package/native-src/src/librats_discovery.cpp +0 -402
- package/native-src/src/librats_encryption.cpp +0 -275
- package/native-src/src/librats_file_transfer.cpp +0 -144
- package/native-src/src/librats_gossipsub.cpp +0 -289
- package/native-src/src/librats_ice.cpp +0 -213
- package/native-src/src/librats_log_macros.h +0 -36
- package/native-src/src/librats_logging.cpp +0 -173
- package/native-src/src/librats_mdns.cpp +0 -166
- package/native-src/src/librats_persistence.cpp +0 -796
- package/native-src/src/librats_portmap.cpp +0 -419
- package/native-src/src/librats_reconnection.cpp +0 -218
- package/native-src/src/librats_statistic.cpp +0 -105
- package/native-src/src/librats_storage.cpp +0 -189
- package/native-src/src/rats_export.h +0 -17
- package/native-src/src/receive_buffer.cpp +0 -82
- package/native-src/src/receive_buffer.h +0 -127
- package/native-src/src/socket.h +0 -228
- package/native-src/src/threadmanager.cpp +0 -105
- package/native-src/src/threadmanager.h +0 -53
- package/native-src/src/tracker.cpp +0 -1264
- package/native-src/src/tracker.h +0 -319
- package/native-src/src/turn.cpp +0 -762
- package/native-src/src/turn.h +0 -460
- package/native-src/src/wakeup_pipe.h +0 -60
- /package/native-src/src/{os.h → librats/util/os.h} +0 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
#include "librats/subsystems/port_mapping_service.h"
|
|
2
|
+
#include "librats/node/node_context.h"
|
|
3
|
+
#include "librats/node/host_events.h"
|
|
4
|
+
#include "librats/nat/upnp.h"
|
|
5
|
+
#include "librats/nat/natpmp.h"
|
|
6
|
+
#include "librats/util/network_utils.h"
|
|
7
|
+
#include "librats/util/logger.h"
|
|
8
|
+
|
|
9
|
+
#include <vector>
|
|
10
|
+
|
|
11
|
+
namespace librats {
|
|
12
|
+
|
|
13
|
+
PortMappingService::PortMappingService(PortMappingConfig config) : config_(config) {}
|
|
14
|
+
|
|
15
|
+
PortMappingService::~PortMappingService() { stop(); }
|
|
16
|
+
|
|
17
|
+
void PortMappingService::attach(NodeContext& ctx) {
|
|
18
|
+
network_ = &ctx.network;
|
|
19
|
+
// On a host network change the LAN IP and/or gateway likely changed, so existing
|
|
20
|
+
// UPnP/NAT-PMP leases are stale or aimed at the wrong internal address. Tear them
|
|
21
|
+
// down and re-run discovery from scratch. The handler runs on the node's
|
|
22
|
+
// maintenance thread (dedicated to recovery), so the blocking stop()/start() is
|
|
23
|
+
// fine here.
|
|
24
|
+
ctx.events.on<NetworkChanged>([this](const NetworkChanged&) {
|
|
25
|
+
if (!config_.enabled) return;
|
|
26
|
+
LOG_INFO("portmap", "Network changed — renewing port mappings");
|
|
27
|
+
stop();
|
|
28
|
+
if (network_) start();
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
void PortMappingService::start() {
|
|
33
|
+
if (!config_.enabled) {
|
|
34
|
+
LOG_DEBUG("portmap", "Automatic port forwarding disabled by config");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const uint16_t port = network_ ? network_->listen_port() : 0;
|
|
39
|
+
if (port == 0) {
|
|
40
|
+
LOG_WARN("portmap", "Skipping port mapping: node has no listen port");
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// One port, mapped under each protocol actually listening on it. Asking for a
|
|
45
|
+
// protocol the node does not serve would install a mapping pointing at nothing,
|
|
46
|
+
// so the node's own transports bitmask — the same one identify advertises — is
|
|
47
|
+
// what decides.
|
|
48
|
+
const uint8_t transports = network_->transports();
|
|
49
|
+
std::vector<PortMapProtocol> protocols;
|
|
50
|
+
if (transports & PeerTransportTcp) protocols.push_back(PortMapProtocol::TCP);
|
|
51
|
+
if (transports & PeerTransportUdp) protocols.push_back(PortMapProtocol::UDP);
|
|
52
|
+
if (protocols.empty()) {
|
|
53
|
+
LOG_WARN("portmap", "Skipping port mapping: node reports no running transport");
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
auto callback = [this](const PortMapResult& r) { handle_result(r); };
|
|
58
|
+
|
|
59
|
+
std::unique_ptr<UpnpClient> upnp;
|
|
60
|
+
std::unique_ptr<NatPmpClient> natpmp;
|
|
61
|
+
|
|
62
|
+
// external_port 0 means "same as internal" in both backends, which is what the
|
|
63
|
+
// UDP mapping needs: peers learn our datagram endpoint from the port the NAT
|
|
64
|
+
// rewrites our outbound traffic to (nat_status.h), and only a port-preserving
|
|
65
|
+
// mapping makes that the same port the router forwards inbound. (A router that
|
|
66
|
+
// rejects the port with a conflict makes UPnP fall back to a random one — still
|
|
67
|
+
// dialable through mapped_public_address(), just no longer the observed one.)
|
|
68
|
+
if (config_.enable_upnp) {
|
|
69
|
+
upnp = std::make_unique<UpnpClient>();
|
|
70
|
+
upnp->set_lease_duration(config_.lease_duration_seconds);
|
|
71
|
+
upnp->set_callback(callback);
|
|
72
|
+
for (PortMapProtocol proto : protocols)
|
|
73
|
+
upnp->add_mapping(proto, port, /*external_port=*/0, "rats");
|
|
74
|
+
}
|
|
75
|
+
if (config_.enable_natpmp) {
|
|
76
|
+
natpmp = std::make_unique<NatPmpClient>();
|
|
77
|
+
natpmp->set_lease_duration(config_.lease_duration_seconds);
|
|
78
|
+
natpmp->set_callback(callback);
|
|
79
|
+
for (PortMapProtocol proto : protocols)
|
|
80
|
+
natpmp->add_mapping(proto, port, /*external_port=*/0);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
{
|
|
84
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
85
|
+
if (upnp_ || natpmp_) return; // already started
|
|
86
|
+
upnp_ = std::move(upnp);
|
|
87
|
+
natpmp_ = std::move(natpmp);
|
|
88
|
+
// Start the workers under the lock so a result callback (which takes the
|
|
89
|
+
// lock from its own thread) cannot observe a half-published state.
|
|
90
|
+
if (upnp_) upnp_->start();
|
|
91
|
+
if (natpmp_) natpmp_->start();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
std::string proto_list;
|
|
95
|
+
for (PortMapProtocol proto : protocols) {
|
|
96
|
+
if (!proto_list.empty()) proto_list += "+";
|
|
97
|
+
proto_list += to_string(proto);
|
|
98
|
+
}
|
|
99
|
+
LOG_INFO("portmap", "Started automatic port forwarding for " << proto_list << " port " << port
|
|
100
|
+
<< " (upnp=" << config_.enable_upnp << " natpmp=" << config_.enable_natpmp
|
|
101
|
+
<< " lease=" << config_.lease_duration_seconds << "s)");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
void PortMappingService::stop() {
|
|
105
|
+
// Move the clients out under the lock, then stop() them outside it: stop()
|
|
106
|
+
// joins worker threads that call handle_result() (which re-takes mutex_), so
|
|
107
|
+
// holding it across stop() would deadlock.
|
|
108
|
+
std::unique_ptr<UpnpClient> upnp;
|
|
109
|
+
std::unique_ptr<NatPmpClient> natpmp;
|
|
110
|
+
{
|
|
111
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
112
|
+
upnp = std::move(upnp_);
|
|
113
|
+
natpmp = std::move(natpmp_);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (upnp || natpmp) LOG_INFO("portmap", "Removing port mappings and stopping backends");
|
|
117
|
+
if (upnp) upnp->stop();
|
|
118
|
+
if (natpmp) natpmp->stop();
|
|
119
|
+
|
|
120
|
+
// The backends have just torn their mappings down, so whatever public endpoint
|
|
121
|
+
// they had established no longer exists. Forget it — NetworkChanged restarts us
|
|
122
|
+
// through here, and reporting the pre-change mapping afterwards would hand out
|
|
123
|
+
// an address that now points at a different LAN.
|
|
124
|
+
{
|
|
125
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
126
|
+
mapped_external_ip_.clear();
|
|
127
|
+
mapped_external_tcp_port_ = 0;
|
|
128
|
+
mapped_external_udp_port_ = 0;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
uint16_t& PortMappingService::external_port_slot(PortMapProtocol protocol) {
|
|
133
|
+
return protocol == PortMapProtocol::TCP ? mapped_external_tcp_port_ : mapped_external_udp_port_;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
void PortMappingService::handle_result(const PortMapResult& result) {
|
|
137
|
+
// A gateway whose reported "external" IP is itself private means we're behind
|
|
138
|
+
// a second NAT (double-NAT): the mapping forwards a port on the inner router,
|
|
139
|
+
// but that doesn't make us reachable from the internet. Such a mapping must
|
|
140
|
+
// NOT be recorded as a usable public endpoint.
|
|
141
|
+
const bool ip_is_private =
|
|
142
|
+
!result.external_ip.empty() && !network_utils::is_public_ip(result.external_ip);
|
|
143
|
+
|
|
144
|
+
PortMapCallback user_cb;
|
|
145
|
+
bool warn_double_nat = false;
|
|
146
|
+
{
|
|
147
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
148
|
+
// Only successes are recorded, and a failure never clears an earlier one:
|
|
149
|
+
// the two backends run in parallel against the same router, so a NAT-PMP
|
|
150
|
+
// refusal routinely arrives after UPnP has already mapped the very same
|
|
151
|
+
// port. Each protocol keeps its own slot — a router may take one and
|
|
152
|
+
// refuse the other.
|
|
153
|
+
if (result.success && !ip_is_private) {
|
|
154
|
+
if (!result.external_ip.empty()) mapped_external_ip_ = result.external_ip;
|
|
155
|
+
external_port_slot(result.protocol) = result.external_port;
|
|
156
|
+
} else if (result.success && ip_is_private && !double_nat_warned_) {
|
|
157
|
+
double_nat_warned_ = true;
|
|
158
|
+
warn_double_nat = true;
|
|
159
|
+
}
|
|
160
|
+
user_cb = user_callback_;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (result.success && ip_is_private) {
|
|
164
|
+
LOG_INFO("portmap", to_string(result.transport) << " mapped " << to_string(result.protocol)
|
|
165
|
+
<< " port " << result.internal_port << " -> external " << result.external_ip << ":"
|
|
166
|
+
<< result.external_port << " (gateway external IP is private — not a usable public address)");
|
|
167
|
+
if (warn_double_nat) {
|
|
168
|
+
LOG_WARN("portmap", "Gateway reports a private external IP (" << result.external_ip
|
|
169
|
+
<< ") — likely double-NAT. Port forwarding alone won't make this host publicly reachable.");
|
|
170
|
+
}
|
|
171
|
+
} else if (result.success) {
|
|
172
|
+
LOG_INFO("portmap", to_string(result.transport) << " mapped " << to_string(result.protocol)
|
|
173
|
+
<< " port " << result.internal_port << " -> external "
|
|
174
|
+
<< (result.external_ip.empty() ? "?" : result.external_ip) << ":" << result.external_port);
|
|
175
|
+
} else {
|
|
176
|
+
LOG_DEBUG("portmap", to_string(result.transport) << " mapping failed: " << result.error);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Invoke the user callback outside the lock to avoid re-entrancy deadlocks.
|
|
180
|
+
if (user_cb) user_cb(result);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
std::optional<std::pair<std::string, uint16_t>>
|
|
184
|
+
PortMappingService::mapped_public_address(PortMapProtocol protocol) const {
|
|
185
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
186
|
+
const uint16_t port = protocol == PortMapProtocol::TCP ? mapped_external_tcp_port_
|
|
187
|
+
: mapped_external_udp_port_;
|
|
188
|
+
if (port == 0 || mapped_external_ip_.empty()) return std::nullopt;
|
|
189
|
+
return std::make_pair(mapped_external_ip_, port);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
} // namespace librats
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file port_mapping_service.h
|
|
5
|
+
* @brief Automatic NAT port forwarding (UPnP IGD + NAT-PMP) as a Subsystem.
|
|
6
|
+
*
|
|
7
|
+
* Wraps the standalone UpnpClient (src/upnp.h) and NatPmpClient (src/natpmp.h)
|
|
8
|
+
* backends into the Node lifecycle. On start() it asks the home router to forward
|
|
9
|
+
* the node's listen port so peers behind NAT can accept inbound connections; on
|
|
10
|
+
* stop() it removes the mappings. Both backends run in parallel on their own worker
|
|
11
|
+
* threads — whichever the router supports wins.
|
|
12
|
+
*
|
|
13
|
+
* The port is forwarded under EVERY protocol the node is actually listening on
|
|
14
|
+
* (PeerNetwork::transports()), not just TCP. Both transports share one listen port
|
|
15
|
+
* by design, and UDP is the dialer's first choice — a TCP-only mapping leaves an
|
|
16
|
+
* inbound peer able to reach us solely over the TCP fallback. It is also the UDP
|
|
17
|
+
* mapping that a hole punch benefits from: a static, port-preserving mapping is
|
|
18
|
+
* what turns the NAT in front of the shared datagram socket into the
|
|
19
|
+
* endpoint-independent kind HolePunch is willing to fire at (see nat_status.h).
|
|
20
|
+
*
|
|
21
|
+
* Threading: the backends invoke our result callback from their own worker
|
|
22
|
+
* threads, so all shared state is guarded by mutex_. stop() moves the clients out
|
|
23
|
+
* under the lock and stops them OUTSIDE it — stop() joins those workers, which
|
|
24
|
+
* take the lock from handle_result(), so holding it across stop() would deadlock.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
#include "librats/util/rats_export.h"
|
|
28
|
+
#include "librats/node/peer_network.h"
|
|
29
|
+
#include "librats/nat/port_mapping.h" // PortMappingConfig, PortMapResult, PortMapCallback
|
|
30
|
+
|
|
31
|
+
#include <cstdint>
|
|
32
|
+
#include <memory>
|
|
33
|
+
#include <mutex>
|
|
34
|
+
#include <optional>
|
|
35
|
+
#include <string>
|
|
36
|
+
#include <utility>
|
|
37
|
+
|
|
38
|
+
namespace librats {
|
|
39
|
+
|
|
40
|
+
class UpnpClient;
|
|
41
|
+
class NatPmpClient;
|
|
42
|
+
|
|
43
|
+
/// Maps the node's TCP listen port through the home router via UPnP and/or
|
|
44
|
+
/// NAT-PMP. Owns its backends' worker threads; reaches the node only for its
|
|
45
|
+
/// listen port (it neither sends nor receives peer traffic).
|
|
46
|
+
class RATS_API PortMappingService final : public Subsystem {
|
|
47
|
+
public:
|
|
48
|
+
explicit PortMappingService(PortMappingConfig config = {});
|
|
49
|
+
~PortMappingService() override;
|
|
50
|
+
|
|
51
|
+
void attach(NodeContext& ctx) override;
|
|
52
|
+
void start() override;
|
|
53
|
+
void stop() override;
|
|
54
|
+
|
|
55
|
+
/// Observe mapping results (established / refreshed / failed). Optional;
|
|
56
|
+
/// invoked from a backend worker thread. Register before start().
|
|
57
|
+
void on_result(PortMapCallback cb) { user_callback_ = std::move(cb); }
|
|
58
|
+
|
|
59
|
+
/// The public endpoint peers should reach us on over @p protocol, once a
|
|
60
|
+
/// backend reports a usable (genuinely public) external IP + port for it.
|
|
61
|
+
/// nullopt until then. The two protocols are mapped independently and a router
|
|
62
|
+
/// may accept one and refuse the other, so ask for the one you intend to dial.
|
|
63
|
+
std::optional<std::pair<std::string, uint16_t>> mapped_public_address(
|
|
64
|
+
PortMapProtocol protocol = PortMapProtocol::TCP) const;
|
|
65
|
+
|
|
66
|
+
private:
|
|
67
|
+
void handle_result(const PortMapResult& result);
|
|
68
|
+
/// The recorded external port for @p protocol. Call under mutex_.
|
|
69
|
+
uint16_t& external_port_slot(PortMapProtocol protocol);
|
|
70
|
+
|
|
71
|
+
PortMappingConfig config_;
|
|
72
|
+
PeerNetwork* network_ = nullptr;
|
|
73
|
+
PortMapCallback user_callback_;
|
|
74
|
+
|
|
75
|
+
mutable std::mutex mutex_; ///< guards the clients and mapped_* below
|
|
76
|
+
std::unique_ptr<UpnpClient> upnp_;
|
|
77
|
+
std::unique_ptr<NatPmpClient> natpmp_;
|
|
78
|
+
std::string mapped_external_ip_;
|
|
79
|
+
uint16_t mapped_external_tcp_port_ = 0;
|
|
80
|
+
uint16_t mapped_external_udp_port_ = 0;
|
|
81
|
+
bool double_nat_warned_ = false;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
} // namespace librats
|