librats 1.0.2 → 2.1.4
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 +137 -332
- package/binding.gyp +16 -3
- package/lib/index.d.ts +271 -696
- package/lib/index.js +383 -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 +396 -179
- package/native-src/LICENSE +1 -1
- package/native-src/src/librats/bindings/rats.cpp +731 -0
- package/native-src/src/librats/bindings/rats.h +352 -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 +42 -0
- package/native-src/src/librats/core/types.h +93 -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/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 +826 -0
- package/native-src/src/librats/node/node.h +333 -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 +137 -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 +532 -0
- package/native-src/src/librats/subsystems/hole_punch.h +266 -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/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 +540 -0
- package/native-src/src/librats/transport/reactor.h +224 -0
- package/native-src/src/librats/transport/reactor_pool.h +81 -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 +110 -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 +1042 -1324
- 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
package/native-src/src/ice.cpp
DELETED
|
@@ -1,893 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file ice.cpp
|
|
3
|
-
* @brief ICE-lite (Interactive Connectivity Establishment) Implementation
|
|
4
|
-
*
|
|
5
|
-
* Implements RFC 5245 ICE-lite for NAT traversal.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
#include "ice.h"
|
|
9
|
-
#include "logger.h"
|
|
10
|
-
#include "network_utils.h"
|
|
11
|
-
#include <algorithm>
|
|
12
|
-
#include <sstream>
|
|
13
|
-
#include <cstring>
|
|
14
|
-
#include <regex>
|
|
15
|
-
#include <iomanip>
|
|
16
|
-
|
|
17
|
-
namespace librats {
|
|
18
|
-
|
|
19
|
-
// ============================================================================
|
|
20
|
-
// Logging Macros
|
|
21
|
-
// ============================================================================
|
|
22
|
-
|
|
23
|
-
#define LOG_ICE_DEBUG(msg) LOG_DEBUG("ice", msg)
|
|
24
|
-
#define LOG_ICE_INFO(msg) LOG_INFO("ice", msg)
|
|
25
|
-
#define LOG_ICE_WARN(msg) LOG_WARN("ice", msg)
|
|
26
|
-
#define LOG_ICE_ERROR(msg) LOG_ERROR("ice", msg)
|
|
27
|
-
|
|
28
|
-
// ============================================================================
|
|
29
|
-
// IceCandidate Implementation
|
|
30
|
-
// ============================================================================
|
|
31
|
-
|
|
32
|
-
uint32_t IceCandidate::compute_priority(IceCandidateType type,
|
|
33
|
-
uint32_t local_preference,
|
|
34
|
-
uint32_t component_id) {
|
|
35
|
-
// RFC 5245 Section 4.1.2.1:
|
|
36
|
-
// priority = (2^24) * type_preference + (2^8) * local_preference + (256 - component_id)
|
|
37
|
-
|
|
38
|
-
uint32_t type_preference;
|
|
39
|
-
switch (type) {
|
|
40
|
-
case IceCandidateType::Host:
|
|
41
|
-
type_preference = ICE_PRIORITY_HOST;
|
|
42
|
-
break;
|
|
43
|
-
case IceCandidateType::ServerReflexive:
|
|
44
|
-
case IceCandidateType::PeerReflexive:
|
|
45
|
-
type_preference = ICE_PRIORITY_SRFLX;
|
|
46
|
-
break;
|
|
47
|
-
case IceCandidateType::Relay:
|
|
48
|
-
type_preference = ICE_PRIORITY_RELAY;
|
|
49
|
-
break;
|
|
50
|
-
default:
|
|
51
|
-
type_preference = 0;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return (type_preference << 24) + (local_preference << 8) + (256 - component_id);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
std::string IceCandidate::generate_foundation(IceCandidateType type,
|
|
58
|
-
const std::string& base_address,
|
|
59
|
-
const std::string& server_address) {
|
|
60
|
-
// Foundation should be unique for same type + base + server combination
|
|
61
|
-
std::stringstream ss;
|
|
62
|
-
|
|
63
|
-
switch (type) {
|
|
64
|
-
case IceCandidateType::Host:
|
|
65
|
-
ss << "host_";
|
|
66
|
-
break;
|
|
67
|
-
case IceCandidateType::ServerReflexive:
|
|
68
|
-
ss << "srflx_";
|
|
69
|
-
break;
|
|
70
|
-
case IceCandidateType::PeerReflexive:
|
|
71
|
-
ss << "prflx_";
|
|
72
|
-
break;
|
|
73
|
-
case IceCandidateType::Relay:
|
|
74
|
-
ss << "relay_";
|
|
75
|
-
break;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Simple hash of base address
|
|
79
|
-
uint32_t hash = 0;
|
|
80
|
-
for (char c : base_address) {
|
|
81
|
-
hash = hash * 31 + static_cast<uint8_t>(c);
|
|
82
|
-
}
|
|
83
|
-
if (!server_address.empty()) {
|
|
84
|
-
for (char c : server_address) {
|
|
85
|
-
hash = hash * 31 + static_cast<uint8_t>(c);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
ss << std::hex << hash;
|
|
90
|
-
return ss.str();
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
std::string IceCandidate::type_string() const {
|
|
94
|
-
switch (type) {
|
|
95
|
-
case IceCandidateType::Host: return "host";
|
|
96
|
-
case IceCandidateType::ServerReflexive: return "srflx";
|
|
97
|
-
case IceCandidateType::PeerReflexive: return "prflx";
|
|
98
|
-
case IceCandidateType::Relay: return "relay";
|
|
99
|
-
default: return "unknown";
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
std::string IceCandidate::to_sdp_attribute() const {
|
|
104
|
-
// Format: candidate:foundation component-id transport priority address port typ type [raddr rport]
|
|
105
|
-
std::stringstream ss;
|
|
106
|
-
ss << "candidate:" << foundation << " "
|
|
107
|
-
<< component_id << " "
|
|
108
|
-
<< (transport == IceTransportProtocol::UDP ? "UDP" : "TCP") << " "
|
|
109
|
-
<< priority << " "
|
|
110
|
-
<< address << " "
|
|
111
|
-
<< port << " "
|
|
112
|
-
<< "typ " << type_string();
|
|
113
|
-
|
|
114
|
-
if (type != IceCandidateType::Host && !related_address.empty()) {
|
|
115
|
-
ss << " raddr " << related_address << " rport " << related_port;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
return ss.str();
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
std::optional<IceCandidate> IceCandidate::from_sdp_attribute(const std::string& sdp) {
|
|
122
|
-
// Parse SDP candidate line
|
|
123
|
-
// Example: candidate:0 1 UDP 2130706431 192.168.1.100 54321 typ host
|
|
124
|
-
|
|
125
|
-
std::string line = sdp;
|
|
126
|
-
|
|
127
|
-
// Remove "a=" prefix if present
|
|
128
|
-
if (line.find("a=") == 0) {
|
|
129
|
-
line = line.substr(2);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Remove "candidate:" prefix if present
|
|
133
|
-
if (line.find("candidate:") == 0) {
|
|
134
|
-
line = line.substr(10);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
std::istringstream iss(line);
|
|
138
|
-
IceCandidate candidate;
|
|
139
|
-
|
|
140
|
-
std::string transport_str, typ_keyword, type_str;
|
|
141
|
-
|
|
142
|
-
// Parse required fields
|
|
143
|
-
if (!(iss >> candidate.foundation >> candidate.component_id >> transport_str
|
|
144
|
-
>> candidate.priority >> candidate.address >> candidate.port
|
|
145
|
-
>> typ_keyword >> type_str)) {
|
|
146
|
-
return std::nullopt;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Parse transport
|
|
150
|
-
std::transform(transport_str.begin(), transport_str.end(), transport_str.begin(), ::toupper);
|
|
151
|
-
candidate.transport = (transport_str == "UDP") ? IceTransportProtocol::UDP : IceTransportProtocol::TCP;
|
|
152
|
-
|
|
153
|
-
// Parse type
|
|
154
|
-
if (type_str == "host") {
|
|
155
|
-
candidate.type = IceCandidateType::Host;
|
|
156
|
-
} else if (type_str == "srflx") {
|
|
157
|
-
candidate.type = IceCandidateType::ServerReflexive;
|
|
158
|
-
} else if (type_str == "prflx") {
|
|
159
|
-
candidate.type = IceCandidateType::PeerReflexive;
|
|
160
|
-
} else if (type_str == "relay") {
|
|
161
|
-
candidate.type = IceCandidateType::Relay;
|
|
162
|
-
} else {
|
|
163
|
-
return std::nullopt;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// Parse optional related address
|
|
167
|
-
std::string token;
|
|
168
|
-
while (iss >> token) {
|
|
169
|
-
if (token == "raddr") {
|
|
170
|
-
iss >> candidate.related_address;
|
|
171
|
-
} else if (token == "rport") {
|
|
172
|
-
iss >> candidate.related_port;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
return candidate;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// ============================================================================
|
|
180
|
-
// IceCandidatePair Implementation
|
|
181
|
-
// ============================================================================
|
|
182
|
-
|
|
183
|
-
uint64_t IceCandidatePair::compute_priority(uint32_t controlling_priority,
|
|
184
|
-
uint32_t controlled_priority,
|
|
185
|
-
bool is_controlling) {
|
|
186
|
-
// RFC 5245 Section 5.7.2:
|
|
187
|
-
// pair priority = 2^32 * MIN(G, D) + 2 * MAX(G, D) + (G > D ? 1 : 0)
|
|
188
|
-
// where G = controlling candidate priority, D = controlled candidate priority
|
|
189
|
-
|
|
190
|
-
uint64_t g = controlling_priority;
|
|
191
|
-
uint64_t d = controlled_priority;
|
|
192
|
-
|
|
193
|
-
uint64_t min_val = (std::min)(g, d);
|
|
194
|
-
uint64_t max_val = (std::max)(g, d);
|
|
195
|
-
|
|
196
|
-
return (min_val << 32) + (max_val << 1) + (g > d ? 1 : 0);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// ============================================================================
|
|
200
|
-
// IceServer Implementation
|
|
201
|
-
// ============================================================================
|
|
202
|
-
|
|
203
|
-
bool IceServer::parse_url(std::string& host, uint16_t& port) const {
|
|
204
|
-
// Parse URL format: stun:host:port or turn:host:port
|
|
205
|
-
std::string url_copy = url;
|
|
206
|
-
|
|
207
|
-
// Remove protocol prefix
|
|
208
|
-
size_t pos = url_copy.find("://");
|
|
209
|
-
if (pos == std::string::npos) {
|
|
210
|
-
pos = url_copy.find(':');
|
|
211
|
-
if (pos != std::string::npos && (url_copy.substr(0, pos) == "stun" ||
|
|
212
|
-
url_copy.substr(0, pos) == "turn" || url_copy.substr(0, pos) == "turns")) {
|
|
213
|
-
url_copy = url_copy.substr(pos + 1);
|
|
214
|
-
}
|
|
215
|
-
} else {
|
|
216
|
-
url_copy = url_copy.substr(pos + 3);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// Find port separator
|
|
220
|
-
pos = url_copy.rfind(':');
|
|
221
|
-
if (pos != std::string::npos) {
|
|
222
|
-
host = url_copy.substr(0, pos);
|
|
223
|
-
try {
|
|
224
|
-
port = static_cast<uint16_t>(std::stoi(url_copy.substr(pos + 1)));
|
|
225
|
-
} catch (...) {
|
|
226
|
-
port = is_turn() ? TURN_DEFAULT_PORT : STUN_DEFAULT_PORT;
|
|
227
|
-
}
|
|
228
|
-
} else {
|
|
229
|
-
host = url_copy;
|
|
230
|
-
port = is_turn() ? TURN_DEFAULT_PORT : STUN_DEFAULT_PORT;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
return !host.empty();
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// ============================================================================
|
|
237
|
-
// IceManager Implementation
|
|
238
|
-
// ============================================================================
|
|
239
|
-
|
|
240
|
-
IceManager::IceManager() {
|
|
241
|
-
stun_client_ = std::make_unique<StunClient>();
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
IceManager::IceManager(const IceConfig& config) : config_(config) {
|
|
245
|
-
stun_client_ = std::make_unique<StunClient>();
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
IceManager::~IceManager() {
|
|
249
|
-
close();
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
void IceManager::set_config(const IceConfig& config) {
|
|
253
|
-
std::lock_guard<std::mutex> lock(mutex_);
|
|
254
|
-
config_ = config;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
void IceManager::add_stun_server(const std::string& host, uint16_t port) {
|
|
258
|
-
std::lock_guard<std::mutex> lock(mutex_);
|
|
259
|
-
config_.add_stun_server(host, port);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
void IceManager::add_turn_server(const std::string& host, uint16_t port,
|
|
263
|
-
const std::string& username, const std::string& password) {
|
|
264
|
-
std::lock_guard<std::mutex> lock(mutex_);
|
|
265
|
-
config_.add_turn_server(host, port, username, password);
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
void IceManager::clear_ice_servers() {
|
|
269
|
-
std::lock_guard<std::mutex> lock(mutex_);
|
|
270
|
-
config_.ice_servers.clear();
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
bool IceManager::ensure_socket() {
|
|
274
|
-
if (is_valid_socket(socket_)) {
|
|
275
|
-
return true;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
socket_ = create_udp_socket(0);
|
|
279
|
-
if (!is_valid_socket(socket_)) {
|
|
280
|
-
LOG_ICE_ERROR("Failed to create UDP socket");
|
|
281
|
-
return false;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
local_port_ = static_cast<uint16_t>(get_bound_port(socket_));
|
|
285
|
-
LOG_ICE_DEBUG("Created ICE socket on port " << local_port_);
|
|
286
|
-
return true;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
// ============================================================================
|
|
290
|
-
// Candidate Gathering
|
|
291
|
-
// ============================================================================
|
|
292
|
-
|
|
293
|
-
bool IceManager::gather_candidates() {
|
|
294
|
-
if (gathering_) {
|
|
295
|
-
LOG_ICE_WARN("Candidate gathering already in progress");
|
|
296
|
-
return false;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
if (!ensure_socket()) {
|
|
300
|
-
return false;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
LOG_ICE_INFO("Starting ICE candidate gathering");
|
|
304
|
-
|
|
305
|
-
gathering_ = true;
|
|
306
|
-
set_gathering_state(IceGatheringState::Gathering);
|
|
307
|
-
|
|
308
|
-
// Clear previous candidates
|
|
309
|
-
{
|
|
310
|
-
std::lock_guard<std::mutex> lock(mutex_);
|
|
311
|
-
local_candidates_.clear();
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
// Start gathering in background thread
|
|
315
|
-
gathering_thread_ = std::thread([this]() {
|
|
316
|
-
// Gather host candidates
|
|
317
|
-
if (config_.gather_host_candidates) {
|
|
318
|
-
gather_host_candidates();
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
// Gather server-reflexive candidates
|
|
322
|
-
if (config_.gather_srflx_candidates) {
|
|
323
|
-
gather_srflx_candidates();
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
// Gather relay candidates
|
|
327
|
-
if (config_.gather_relay_candidates) {
|
|
328
|
-
gather_relay_candidates();
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
gathering_complete();
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
return true;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
void IceManager::gather_host_candidates() {
|
|
338
|
-
LOG_ICE_DEBUG("Gathering host candidates");
|
|
339
|
-
|
|
340
|
-
// Get local interface addresses
|
|
341
|
-
auto addresses = network_utils::get_local_interface_addresses();
|
|
342
|
-
|
|
343
|
-
for (const auto& addr : addresses) {
|
|
344
|
-
// Skip loopback and link-local for now
|
|
345
|
-
if (addr.find("127.") == 0 || addr.find("::1") == 0) {
|
|
346
|
-
continue;
|
|
347
|
-
}
|
|
348
|
-
if (addr.find("169.254.") == 0 || addr.find("fe80:") == 0) {
|
|
349
|
-
continue;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
IceCandidate candidate;
|
|
353
|
-
candidate.type = IceCandidateType::Host;
|
|
354
|
-
candidate.address = addr;
|
|
355
|
-
candidate.port = local_port_;
|
|
356
|
-
candidate.transport = IceTransportProtocol::UDP;
|
|
357
|
-
candidate.component_id = 1;
|
|
358
|
-
candidate.foundation = IceCandidate::generate_foundation(
|
|
359
|
-
IceCandidateType::Host, addr);
|
|
360
|
-
candidate.priority = IceCandidate::compute_priority(
|
|
361
|
-
IceCandidateType::Host, 65535, 1);
|
|
362
|
-
|
|
363
|
-
add_local_candidate(candidate);
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
void IceManager::gather_srflx_candidates() {
|
|
368
|
-
LOG_ICE_DEBUG("Gathering server-reflexive candidates");
|
|
369
|
-
|
|
370
|
-
std::vector<IceServer> stun_servers;
|
|
371
|
-
{
|
|
372
|
-
std::lock_guard<std::mutex> lock(mutex_);
|
|
373
|
-
for (const auto& server : config_.ice_servers) {
|
|
374
|
-
if (server.is_stun()) {
|
|
375
|
-
stun_servers.push_back(server);
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
for (const auto& server : stun_servers) {
|
|
381
|
-
std::string host;
|
|
382
|
-
uint16_t port;
|
|
383
|
-
if (!server.parse_url(host, port)) {
|
|
384
|
-
continue;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
LOG_ICE_DEBUG("Querying STUN server: " << host << ":" << port);
|
|
388
|
-
|
|
389
|
-
auto result = stun_client_->binding_request_with_socket(
|
|
390
|
-
socket_, host, port, config_.gathering_timeout_ms);
|
|
391
|
-
|
|
392
|
-
if (result.success && result.mapped_address) {
|
|
393
|
-
IceCandidate candidate;
|
|
394
|
-
candidate.type = IceCandidateType::ServerReflexive;
|
|
395
|
-
candidate.address = result.mapped_address->address;
|
|
396
|
-
candidate.port = result.mapped_address->port;
|
|
397
|
-
candidate.transport = IceTransportProtocol::UDP;
|
|
398
|
-
candidate.component_id = 1;
|
|
399
|
-
|
|
400
|
-
// Get related (base) address
|
|
401
|
-
auto local_addrs = network_utils::get_local_interface_addresses();
|
|
402
|
-
if (!local_addrs.empty()) {
|
|
403
|
-
candidate.related_address = local_addrs[0];
|
|
404
|
-
candidate.related_port = local_port_;
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
candidate.foundation = IceCandidate::generate_foundation(
|
|
408
|
-
IceCandidateType::ServerReflexive, candidate.related_address, host);
|
|
409
|
-
candidate.priority = IceCandidate::compute_priority(
|
|
410
|
-
IceCandidateType::ServerReflexive, 65534, 1);
|
|
411
|
-
|
|
412
|
-
add_local_candidate(candidate);
|
|
413
|
-
|
|
414
|
-
LOG_ICE_INFO("Discovered public address: " << candidate.address_string());
|
|
415
|
-
break; // One srflx candidate is usually enough
|
|
416
|
-
} else {
|
|
417
|
-
LOG_ICE_WARN("STUN request failed for " << host << ":" << port);
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
void IceManager::gather_relay_candidates() {
|
|
423
|
-
LOG_ICE_DEBUG("Gathering relay candidates");
|
|
424
|
-
|
|
425
|
-
std::vector<IceServer> turn_servers;
|
|
426
|
-
{
|
|
427
|
-
std::lock_guard<std::mutex> lock(mutex_);
|
|
428
|
-
for (const auto& server : config_.ice_servers) {
|
|
429
|
-
if (server.is_turn()) {
|
|
430
|
-
turn_servers.push_back(server);
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
for (const auto& server : turn_servers) {
|
|
436
|
-
std::string host;
|
|
437
|
-
uint16_t port;
|
|
438
|
-
if (!server.parse_url(host, port)) {
|
|
439
|
-
continue;
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
LOG_ICE_DEBUG("Allocating TURN relay: " << host << ":" << port);
|
|
443
|
-
|
|
444
|
-
TurnClientConfig turn_config;
|
|
445
|
-
turn_config.server = host;
|
|
446
|
-
turn_config.port = port;
|
|
447
|
-
turn_config.username = server.username;
|
|
448
|
-
turn_config.password = server.password;
|
|
449
|
-
turn_config.timeout_ms = config_.gathering_timeout_ms;
|
|
450
|
-
turn_config.auto_refresh = true;
|
|
451
|
-
|
|
452
|
-
turn_client_ = std::make_unique<TurnClient>(turn_config);
|
|
453
|
-
auto result = turn_client_->allocate();
|
|
454
|
-
|
|
455
|
-
if (result.success && turn_client_->is_allocated()) {
|
|
456
|
-
const auto& alloc = turn_client_->get_allocation();
|
|
457
|
-
|
|
458
|
-
IceCandidate candidate;
|
|
459
|
-
candidate.type = IceCandidateType::Relay;
|
|
460
|
-
candidate.address = alloc.relay_address.address;
|
|
461
|
-
candidate.port = alloc.relay_address.port;
|
|
462
|
-
candidate.transport = IceTransportProtocol::UDP;
|
|
463
|
-
candidate.component_id = 1;
|
|
464
|
-
|
|
465
|
-
auto local_addrs = network_utils::get_local_interface_addresses();
|
|
466
|
-
if (!local_addrs.empty()) {
|
|
467
|
-
candidate.related_address = local_addrs[0];
|
|
468
|
-
candidate.related_port = local_port_;
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
candidate.foundation = IceCandidate::generate_foundation(
|
|
472
|
-
IceCandidateType::Relay, candidate.related_address, host);
|
|
473
|
-
candidate.priority = IceCandidate::compute_priority(
|
|
474
|
-
IceCandidateType::Relay, 65533, 1);
|
|
475
|
-
|
|
476
|
-
add_local_candidate(candidate);
|
|
477
|
-
|
|
478
|
-
LOG_ICE_INFO("Got relay address: " << candidate.address_string());
|
|
479
|
-
break; // One relay is usually enough
|
|
480
|
-
} else {
|
|
481
|
-
LOG_ICE_WARN("TURN allocation failed for " << host << ":" << port);
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
void IceManager::add_local_candidate(const IceCandidate& candidate) {
|
|
487
|
-
{
|
|
488
|
-
std::lock_guard<std::mutex> lock(mutex_);
|
|
489
|
-
|
|
490
|
-
// Check for duplicates
|
|
491
|
-
for (const auto& c : local_candidates_) {
|
|
492
|
-
if (c == candidate) {
|
|
493
|
-
return;
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
local_candidates_.push_back(candidate);
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
LOG_ICE_DEBUG("Added local candidate: " << candidate.type_string()
|
|
501
|
-
<< " " << candidate.address_string());
|
|
502
|
-
|
|
503
|
-
// Notify callback (trickle ICE)
|
|
504
|
-
if (on_new_candidate_) {
|
|
505
|
-
on_new_candidate_(candidate);
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
void IceManager::gathering_complete() {
|
|
510
|
-
gathering_ = false;
|
|
511
|
-
|
|
512
|
-
std::vector<IceCandidate> candidates;
|
|
513
|
-
{
|
|
514
|
-
std::lock_guard<std::mutex> lock(mutex_);
|
|
515
|
-
candidates = local_candidates_;
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
LOG_ICE_INFO("Candidate gathering complete: " << candidates.size() << " candidates");
|
|
519
|
-
|
|
520
|
-
set_gathering_state(IceGatheringState::Complete);
|
|
521
|
-
|
|
522
|
-
if (on_candidates_gathered_) {
|
|
523
|
-
on_candidates_gathered_(candidates);
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
// Form initial candidate pairs if we have remote candidates
|
|
527
|
-
form_candidate_pairs();
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
std::vector<IceCandidate> IceManager::get_local_candidates() const {
|
|
531
|
-
std::lock_guard<std::mutex> lock(mutex_);
|
|
532
|
-
return local_candidates_;
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
// ============================================================================
|
|
536
|
-
// Remote Candidates
|
|
537
|
-
// ============================================================================
|
|
538
|
-
|
|
539
|
-
void IceManager::add_remote_candidate(const IceCandidate& candidate) {
|
|
540
|
-
{
|
|
541
|
-
std::lock_guard<std::mutex> lock(mutex_);
|
|
542
|
-
|
|
543
|
-
// Check for duplicates
|
|
544
|
-
for (const auto& c : remote_candidates_) {
|
|
545
|
-
if (c == candidate) {
|
|
546
|
-
return;
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
remote_candidates_.push_back(candidate);
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
LOG_ICE_DEBUG("Added remote candidate: " << candidate.type_string()
|
|
554
|
-
<< " " << candidate.address_string());
|
|
555
|
-
|
|
556
|
-
// Update candidate pairs
|
|
557
|
-
form_candidate_pairs();
|
|
558
|
-
|
|
559
|
-
// Start checking if not already running
|
|
560
|
-
if (!checking_ && gathering_state_ == IceGatheringState::Complete) {
|
|
561
|
-
start_checks();
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
void IceManager::add_remote_candidates_from_sdp(const std::vector<std::string>& sdp_lines) {
|
|
566
|
-
for (const auto& line : sdp_lines) {
|
|
567
|
-
auto candidate = IceCandidate::from_sdp_attribute(line);
|
|
568
|
-
if (candidate) {
|
|
569
|
-
add_remote_candidate(*candidate);
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
std::vector<IceCandidate> IceManager::get_remote_candidates() const {
|
|
575
|
-
std::lock_guard<std::mutex> lock(mutex_);
|
|
576
|
-
return remote_candidates_;
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
void IceManager::end_of_remote_candidates() {
|
|
580
|
-
remote_candidates_complete_ = true;
|
|
581
|
-
|
|
582
|
-
// Start checks if not already running
|
|
583
|
-
if (!checking_ && gathering_state_ == IceGatheringState::Complete) {
|
|
584
|
-
start_checks();
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
// ============================================================================
|
|
589
|
-
// Connectivity Checks
|
|
590
|
-
// ============================================================================
|
|
591
|
-
|
|
592
|
-
void IceManager::form_candidate_pairs() {
|
|
593
|
-
std::lock_guard<std::mutex> lock(mutex_);
|
|
594
|
-
|
|
595
|
-
// Clear existing pairs
|
|
596
|
-
candidate_pairs_.clear();
|
|
597
|
-
|
|
598
|
-
// Form pairs from local and remote candidates
|
|
599
|
-
for (const auto& local : local_candidates_) {
|
|
600
|
-
for (const auto& remote : remote_candidates_) {
|
|
601
|
-
// Only pair UDP with UDP, same component
|
|
602
|
-
if (local.transport != remote.transport ||
|
|
603
|
-
local.component_id != remote.component_id) {
|
|
604
|
-
continue;
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
IceCandidatePair pair;
|
|
608
|
-
pair.local = local;
|
|
609
|
-
pair.remote = remote;
|
|
610
|
-
pair.state = IceCandidatePairState::Frozen;
|
|
611
|
-
|
|
612
|
-
// ICE-lite is always controlled, so remote is controlling
|
|
613
|
-
pair.priority = IceCandidatePair::compute_priority(
|
|
614
|
-
remote.priority, local.priority, false);
|
|
615
|
-
|
|
616
|
-
candidate_pairs_.push_back(pair);
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
// Sort by priority (highest first)
|
|
621
|
-
std::sort(candidate_pairs_.begin(), candidate_pairs_.end(),
|
|
622
|
-
[](const IceCandidatePair& a, const IceCandidatePair& b) {
|
|
623
|
-
return a.priority > b.priority;
|
|
624
|
-
});
|
|
625
|
-
|
|
626
|
-
LOG_ICE_DEBUG("Formed " << candidate_pairs_.size() << " candidate pairs");
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
void IceManager::start_checks() {
|
|
630
|
-
if (checking_) {
|
|
631
|
-
return;
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
{
|
|
635
|
-
std::lock_guard<std::mutex> lock(mutex_);
|
|
636
|
-
if (candidate_pairs_.empty()) {
|
|
637
|
-
LOG_ICE_WARN("No candidate pairs to check");
|
|
638
|
-
return;
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
LOG_ICE_INFO("Starting connectivity checks");
|
|
643
|
-
|
|
644
|
-
checking_ = true;
|
|
645
|
-
set_connection_state(IceConnectionState::Checking);
|
|
646
|
-
|
|
647
|
-
checking_thread_ = std::thread(&IceManager::perform_connectivity_checks, this);
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
void IceManager::stop_checks() {
|
|
651
|
-
checking_ = false;
|
|
652
|
-
if (checking_thread_.joinable()) {
|
|
653
|
-
checking_thread_.join();
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
void IceManager::perform_connectivity_checks() {
|
|
658
|
-
while (checking_) {
|
|
659
|
-
IceCandidatePair* next_pair = nullptr;
|
|
660
|
-
|
|
661
|
-
{
|
|
662
|
-
std::lock_guard<std::mutex> lock(mutex_);
|
|
663
|
-
|
|
664
|
-
// Find next pair to check
|
|
665
|
-
for (auto& pair : candidate_pairs_) {
|
|
666
|
-
if (pair.state == IceCandidatePairState::Frozen ||
|
|
667
|
-
pair.state == IceCandidatePairState::Waiting) {
|
|
668
|
-
|
|
669
|
-
// Check if we should retry
|
|
670
|
-
if (pair.state == IceCandidatePairState::Waiting &&
|
|
671
|
-
pair.check_count >= config_.check_max_retries) {
|
|
672
|
-
pair.state = IceCandidatePairState::Failed;
|
|
673
|
-
continue;
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
next_pair = &pair;
|
|
677
|
-
break;
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
if (!next_pair) {
|
|
683
|
-
// No more pairs to check
|
|
684
|
-
update_connection_state();
|
|
685
|
-
break;
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
next_pair->state = IceCandidatePairState::InProgress;
|
|
689
|
-
next_pair->check_count++;
|
|
690
|
-
next_pair->last_check = std::chrono::steady_clock::now();
|
|
691
|
-
|
|
692
|
-
bool success = perform_check(*next_pair);
|
|
693
|
-
|
|
694
|
-
{
|
|
695
|
-
std::lock_guard<std::mutex> lock(mutex_);
|
|
696
|
-
if (success) {
|
|
697
|
-
next_pair->state = IceCandidatePairState::Succeeded;
|
|
698
|
-
LOG_ICE_INFO("Connectivity check succeeded: " << next_pair->key());
|
|
699
|
-
|
|
700
|
-
// First successful pair
|
|
701
|
-
if (connection_state_ == IceConnectionState::Checking) {
|
|
702
|
-
set_connection_state(IceConnectionState::Connected);
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
select_best_pair();
|
|
706
|
-
} else {
|
|
707
|
-
next_pair->state = IceCandidatePairState::Waiting; // Will retry
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
update_connection_state();
|
|
715
|
-
}
|
|
716
|
-
|
|
717
|
-
bool IceManager::perform_check(IceCandidatePair& pair) {
|
|
718
|
-
// Send STUN binding request to remote candidate
|
|
719
|
-
StunMessage request(StunMessageType::BindingRequest);
|
|
720
|
-
|
|
721
|
-
if (!config_.software.empty()) {
|
|
722
|
-
request.add_software(config_.software);
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
// TODO: Add ICE-specific attributes (USE-CANDIDATE, PRIORITY, ICE-CONTROLLING/CONTROLLED)
|
|
726
|
-
|
|
727
|
-
auto response = stun_client_->send_request(
|
|
728
|
-
socket_, request, pair.remote.address, pair.remote.port,
|
|
729
|
-
config_.check_timeout_ms);
|
|
730
|
-
|
|
731
|
-
return response.has_value() && response->is_success_response();
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
void IceManager::update_connection_state() {
|
|
735
|
-
std::lock_guard<std::mutex> lock(mutex_);
|
|
736
|
-
|
|
737
|
-
bool has_succeeded = false;
|
|
738
|
-
bool all_failed = true;
|
|
739
|
-
|
|
740
|
-
for (const auto& pair : candidate_pairs_) {
|
|
741
|
-
if (pair.state == IceCandidatePairState::Succeeded) {
|
|
742
|
-
has_succeeded = true;
|
|
743
|
-
all_failed = false;
|
|
744
|
-
} else if (pair.state != IceCandidatePairState::Failed) {
|
|
745
|
-
all_failed = false;
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
if (has_succeeded && remote_candidates_complete_) {
|
|
750
|
-
set_connection_state(IceConnectionState::Completed);
|
|
751
|
-
} else if (all_failed && remote_candidates_complete_) {
|
|
752
|
-
set_connection_state(IceConnectionState::Failed);
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
void IceManager::select_best_pair() {
|
|
757
|
-
// Find highest priority succeeded pair
|
|
758
|
-
for (auto& pair : candidate_pairs_) {
|
|
759
|
-
if (pair.state == IceCandidatePairState::Succeeded) {
|
|
760
|
-
pair.nominated = true;
|
|
761
|
-
selected_pair_ = pair;
|
|
762
|
-
|
|
763
|
-
LOG_ICE_INFO("Selected pair: " << pair.key());
|
|
764
|
-
|
|
765
|
-
if (on_selected_pair_) {
|
|
766
|
-
on_selected_pair_(pair);
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
break;
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
|
|
774
|
-
std::vector<IceCandidatePair> IceManager::get_candidate_pairs() const {
|
|
775
|
-
std::lock_guard<std::mutex> lock(mutex_);
|
|
776
|
-
return candidate_pairs_;
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
std::optional<IceCandidatePair> IceManager::get_selected_pair() const {
|
|
780
|
-
std::lock_guard<std::mutex> lock(mutex_);
|
|
781
|
-
return selected_pair_;
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
// ============================================================================
|
|
785
|
-
// Public Address Discovery
|
|
786
|
-
// ============================================================================
|
|
787
|
-
|
|
788
|
-
std::optional<std::pair<std::string, uint16_t>> IceManager::get_public_address() const {
|
|
789
|
-
std::lock_guard<std::mutex> lock(mutex_);
|
|
790
|
-
|
|
791
|
-
for (const auto& c : local_candidates_) {
|
|
792
|
-
if (c.type == IceCandidateType::ServerReflexive) {
|
|
793
|
-
return std::make_pair(c.address, c.port);
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
|
|
797
|
-
return std::nullopt;
|
|
798
|
-
}
|
|
799
|
-
|
|
800
|
-
// ============================================================================
|
|
801
|
-
// Callbacks
|
|
802
|
-
// ============================================================================
|
|
803
|
-
|
|
804
|
-
void IceManager::set_on_candidates_gathered(IceCandidatesCallback callback) {
|
|
805
|
-
on_candidates_gathered_ = std::move(callback);
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
void IceManager::set_on_new_candidate(IceNewCandidateCallback callback) {
|
|
809
|
-
on_new_candidate_ = std::move(callback);
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
void IceManager::set_on_gathering_state_changed(IceGatheringStateCallback callback) {
|
|
813
|
-
on_gathering_state_changed_ = std::move(callback);
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
void IceManager::set_on_connection_state_changed(IceConnectionStateCallback callback) {
|
|
817
|
-
on_connection_state_changed_ = std::move(callback);
|
|
818
|
-
}
|
|
819
|
-
|
|
820
|
-
void IceManager::set_on_selected_pair(IceSelectedPairCallback callback) {
|
|
821
|
-
on_selected_pair_ = std::move(callback);
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
// ============================================================================
|
|
825
|
-
// State Management
|
|
826
|
-
// ============================================================================
|
|
827
|
-
|
|
828
|
-
void IceManager::set_gathering_state(IceGatheringState state) {
|
|
829
|
-
if (gathering_state_ != state) {
|
|
830
|
-
gathering_state_ = state;
|
|
831
|
-
if (on_gathering_state_changed_) {
|
|
832
|
-
on_gathering_state_changed_(state);
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
|
|
837
|
-
void IceManager::set_connection_state(IceConnectionState state) {
|
|
838
|
-
if (connection_state_ != state) {
|
|
839
|
-
connection_state_ = state;
|
|
840
|
-
if (on_connection_state_changed_) {
|
|
841
|
-
on_connection_state_changed_(state);
|
|
842
|
-
}
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
|
|
846
|
-
// ============================================================================
|
|
847
|
-
// Lifecycle
|
|
848
|
-
// ============================================================================
|
|
849
|
-
|
|
850
|
-
void IceManager::close() {
|
|
851
|
-
gathering_ = false;
|
|
852
|
-
checking_ = false;
|
|
853
|
-
|
|
854
|
-
if (gathering_thread_.joinable()) {
|
|
855
|
-
gathering_thread_.join();
|
|
856
|
-
}
|
|
857
|
-
|
|
858
|
-
if (checking_thread_.joinable()) {
|
|
859
|
-
checking_thread_.join();
|
|
860
|
-
}
|
|
861
|
-
|
|
862
|
-
if (turn_client_) {
|
|
863
|
-
turn_client_->close();
|
|
864
|
-
turn_client_.reset();
|
|
865
|
-
}
|
|
866
|
-
|
|
867
|
-
if (is_valid_socket(socket_)) {
|
|
868
|
-
close_socket(socket_);
|
|
869
|
-
socket_ = INVALID_SOCKET_VALUE;
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
{
|
|
873
|
-
std::lock_guard<std::mutex> lock(mutex_);
|
|
874
|
-
local_candidates_.clear();
|
|
875
|
-
remote_candidates_.clear();
|
|
876
|
-
candidate_pairs_.clear();
|
|
877
|
-
selected_pair_.reset();
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
set_connection_state(IceConnectionState::Closed);
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
void IceManager::restart() {
|
|
884
|
-
close();
|
|
885
|
-
|
|
886
|
-
connection_state_ = IceConnectionState::New;
|
|
887
|
-
gathering_state_ = IceGatheringState::New;
|
|
888
|
-
remote_candidates_complete_ = false;
|
|
889
|
-
|
|
890
|
-
gather_candidates();
|
|
891
|
-
}
|
|
892
|
-
|
|
893
|
-
} // namespace librats
|