Back to Site
Loading...
Searching...
No Matches
ice.h
Go to the documentation of this file.
1#pragma once
2
14#include "stun.h"
15#include "turn.h"
16#include "socket.h"
17#include <vector>
18#include <string>
19#include <optional>
20#include <memory>
21#include <mutex>
22#include <functional>
23#include <chrono>
24#include <atomic>
25#include <thread>
26
27namespace librats {
28
29// ============================================================================
30// ICE Constants
31// ============================================================================
32
34constexpr uint32_t ICE_PRIORITY_HOST = 126;
35
37constexpr uint32_t ICE_PRIORITY_SRFLX = 100;
38
40constexpr uint32_t ICE_PRIORITY_RELAY = 0;
41
43constexpr int ICE_CHECK_TIMEOUT_MS = 500;
44
46constexpr int ICE_CHECK_MAX_RETRIES = 5;
47
48// ============================================================================
49// ICE Data Structures
50// ============================================================================
51
55enum class IceCandidateType {
56 Host,
59 Relay
60};
61
66 UDP,
67 TCP
68};
69
74 New,
75 Gathering,
76 Checking,
77 Connected,
78 Completed,
79 Failed,
81 Closed
82};
83
88 New,
89 Gathering,
91};
92
98 std::string foundation;
99 uint32_t component_id;
101 uint32_t priority;
102 std::string address;
103 uint16_t port;
104 std::string related_address;
105 uint16_t related_port;
106
110
115 uint32_t local_preference = 65535,
116 uint32_t component_id = 1);
117
122 const std::string& base_address,
123 const std::string& server_address = "");
124
128 std::string to_sdp_attribute() const;
129
133 static std::optional<IceCandidate> from_sdp_attribute(const std::string& sdp);
134
138 std::string type_string() const;
139
143 std::string address_string() const {
144 return address + ":" + std::to_string(port);
145 }
146
147 bool operator==(const IceCandidate& other) const {
148 return type == other.type && address == other.address &&
149 port == other.port && transport == other.transport;
150 }
151};
152
157 Frozen,
158 Waiting,
159 InProgress,
160 Succeeded,
161 Failed
162};
163
171 uint64_t priority;
174 std::chrono::steady_clock::time_point last_check;
175
178
182 static uint64_t compute_priority(uint32_t controlling_priority,
183 uint32_t controlled_priority,
184 bool is_controlling);
185
189 std::string key() const {
190 return local.address_string() + "->" + remote.address_string();
191 }
192};
193
197struct IceServer {
198 std::string url;
199 std::string username;
200 std::string password;
201
202 IceServer() = default;
203 IceServer(const std::string& u) : url(u) {}
204 IceServer(const std::string& u, const std::string& user, const std::string& pass)
205 : url(u), username(user), password(pass) {}
206
210 bool is_stun() const { return url.find("stun:") == 0; }
211
215 bool is_turn() const { return url.find("turn:") == 0 || url.find("turns:") == 0; }
216
220 bool parse_url(std::string& host, uint16_t& port) const;
221};
222
226struct IceConfig {
227 std::vector<IceServer> ice_servers;
234 std::string software = "librats";
235
236 IceConfig() = default;
237
241 void add_stun_server(const std::string& host, uint16_t port = STUN_DEFAULT_PORT) {
242 ice_servers.emplace_back("stun:" + host + ":" + std::to_string(port));
243 }
244
248 void add_turn_server(const std::string& host, uint16_t port,
249 const std::string& username, const std::string& password) {
250 ice_servers.emplace_back("turn:" + host + ":" + std::to_string(port),
251 username, password);
252 }
253};
254
255// ============================================================================
256// ICE Callbacks
257// ============================================================================
258
260using IceCandidatesCallback = std::function<void(const std::vector<IceCandidate>&)>;
261
263using IceGatheringStateCallback = std::function<void(IceGatheringState)>;
264
267
269using IceNewCandidateCallback = std::function<void(const IceCandidate&)>;
270
272using IceSelectedPairCallback = std::function<void(const IceCandidatePair&)>;
273
274// ============================================================================
275// ICE Manager
276// ============================================================================
277
322public:
324 explicit IceManager(const IceConfig& config);
326
327 // Non-copyable
328 IceManager(const IceManager&) = delete;
329 IceManager& operator=(const IceManager&) = delete;
330
331 // =========================================================================
332 // Configuration
333 // =========================================================================
334
339
343 const IceConfig& config() const { return config_; }
344
348 void add_stun_server(const std::string& host, uint16_t port = STUN_DEFAULT_PORT);
349
353 void add_turn_server(const std::string& host, uint16_t port,
354 const std::string& username, const std::string& password);
355
360
361 // =========================================================================
362 // Candidate Gathering
363 // =========================================================================
364
370
374 std::vector<IceCandidate> get_local_candidates() const;
375
379 IceGatheringState get_gathering_state() const { return gathering_state_; }
380
384 bool is_gathering_complete() const {
385 return gathering_state_ == IceGatheringState::Complete;
386 }
387
388 // =========================================================================
389 // Remote Candidates
390 // =========================================================================
391
396 void add_remote_candidate(const IceCandidate& candidate);
397
402 void add_remote_candidates_from_sdp(const std::vector<std::string>& sdp_lines);
403
407 std::vector<IceCandidate> get_remote_candidates() const;
408
413
414 // =========================================================================
415 // Connectivity Checks
416 // =========================================================================
417
422
427
431 std::vector<IceCandidatePair> get_candidate_pairs() const;
432
436 std::optional<IceCandidatePair> get_selected_pair() const;
437
438 // =========================================================================
439 // Connection State
440 // =========================================================================
441
445 IceConnectionState get_connection_state() const { return connection_state_; }
446
450 bool is_connected() const {
451 return connection_state_ == IceConnectionState::Connected ||
452 connection_state_ == IceConnectionState::Completed;
453 }
454
455 // =========================================================================
456 // Public Address Discovery
457 // =========================================================================
458
463 std::optional<std::pair<std::string, uint16_t>> get_public_address() const;
464
465 // =========================================================================
466 // Socket Access
467 // =========================================================================
468
473 socket_t get_socket() const { return socket_; }
474
478 uint16_t get_local_port() const { return local_port_; }
479
480 // =========================================================================
481 // Callbacks
482 // =========================================================================
483
489
490 // =========================================================================
491 // Lifecycle
492 // =========================================================================
493
497 void close();
498
502 void restart();
503
504private:
505 // Configuration
506 IceConfig config_;
507
508 // Network
510 uint16_t local_port_ = 0;
511
512 // STUN/TURN clients
513 std::unique_ptr<StunClient> stun_client_;
514 std::unique_ptr<TurnClient> turn_client_;
515
516 // State
517 mutable std::mutex mutex_;
518 IceGatheringState gathering_state_ = IceGatheringState::New;
520
521 // Candidates
522 std::vector<IceCandidate> local_candidates_;
523 std::vector<IceCandidate> remote_candidates_;
524 std::vector<IceCandidatePair> candidate_pairs_;
525 std::optional<IceCandidatePair> selected_pair_;
526
527 // Flags
528 std::atomic<bool> gathering_ {false};
529 std::atomic<bool> checking_ {false};
530 bool remote_candidates_complete_ = false;
531
532 // Threads
533 std::thread gathering_thread_;
534 std::thread checking_thread_;
535
536 // Callbacks
537 IceCandidatesCallback on_candidates_gathered_;
538 IceNewCandidateCallback on_new_candidate_;
539 IceGatheringStateCallback on_gathering_state_changed_;
540 IceConnectionStateCallback on_connection_state_changed_;
541 IceSelectedPairCallback on_selected_pair_;
542
543 // Internal methods
544 bool ensure_socket();
545 void gather_host_candidates();
546 void gather_srflx_candidates();
547 void gather_relay_candidates();
548 void gathering_complete();
549 void add_local_candidate(const IceCandidate& candidate);
550 void form_candidate_pairs();
551 void perform_connectivity_checks();
552 bool perform_check(IceCandidatePair& pair);
553 void update_connection_state();
554 void select_best_pair();
555 void set_gathering_state(IceGatheringState state);
556 void set_connection_state(IceConnectionState state);
557};
558
559} // namespace librats
ICE-lite Manager for NAT traversal.
Definition ice.h:321
void stop_checks()
Stop connectivity checks.
std::vector< IceCandidatePair > get_candidate_pairs() const
Get candidate pairs.
std::optional< std::pair< std::string, uint16_t > > get_public_address() const
Get our public address (from server-reflexive candidate)
void set_on_connection_state_changed(IceConnectionStateCallback callback)
void clear_ice_servers()
Clear all ICE servers.
IceGatheringState get_gathering_state() const
Get gathering state.
Definition ice.h:379
void set_on_gathering_state_changed(IceGatheringStateCallback callback)
IceManager & operator=(const IceManager &)=delete
IceManager(const IceConfig &config)
void close()
Close ICE manager and release resources.
void add_turn_server(const std::string &host, uint16_t port, const std::string &username, const std::string &password)
Add a TURN server with credentials.
bool is_gathering_complete() const
Check if gathering is complete.
Definition ice.h:384
void add_stun_server(const std::string &host, uint16_t port=STUN_DEFAULT_PORT)
Add a STUN server.
std::vector< IceCandidate > get_local_candidates() const
Get local candidates.
void restart()
Restart ICE (gather new candidates and start checks)
uint16_t get_local_port() const
Get local port.
Definition ice.h:478
void start_checks()
Start connectivity checks.
void add_remote_candidate(const IceCandidate &candidate)
Add a remote candidate.
IceManager(const IceManager &)=delete
std::vector< IceCandidate > get_remote_candidates() const
Get remote candidates.
void set_on_new_candidate(IceNewCandidateCallback callback)
std::optional< IceCandidatePair > get_selected_pair() const
Get the selected (best) candidate pair.
IceConnectionState get_connection_state() const
Get connection state.
Definition ice.h:445
void set_on_selected_pair(IceSelectedPairCallback callback)
bool gather_candidates()
Start gathering ICE candidates.
const IceConfig & config() const
Get current configuration.
Definition ice.h:343
void set_config(const IceConfig &config)
Set ICE configuration.
socket_t get_socket() const
Get the UDP socket used for ICE Can be used for data transfer after ICE completes.
Definition ice.h:473
void add_remote_candidates_from_sdp(const std::vector< std::string > &sdp_lines)
Add remote candidates from SDP.
void set_on_candidates_gathered(IceCandidatesCallback callback)
bool is_connected() const
Check if connected.
Definition ice.h:450
void end_of_remote_candidates()
Signal end of remote candidates (for trickle ICE)
constexpr uint32_t ICE_PRIORITY_RELAY
Default ICE candidate priority for relay candidates.
Definition ice.h:40
IceGatheringState
ICE gathering state.
Definition ice.h:87
@ Complete
Gathering complete.
std::function< void(IceGatheringState)> IceGatheringStateCallback
Callback when gathering state changes.
Definition ice.h:263
IceCandidateType
ICE candidate type.
Definition ice.h:55
@ PeerReflexive
Address discovered during connectivity checks.
@ Relay
TURN relay address.
@ ServerReflexive
Address discovered via STUN (public address)
@ Host
Local interface address.
constexpr uint32_t ICE_PRIORITY_HOST
Default ICE candidate priority for host candidates.
Definition ice.h:34
std::function< void(const IceCandidate &)> IceNewCandidateCallback
Callback when a new candidate is discovered (trickle ICE)
Definition ice.h:269
IceCandidatePairState
ICE candidate pair state.
Definition ice.h:156
@ InProgress
Check in progress.
@ Waiting
Waiting to be checked.
std::function< void(const std::vector< IceCandidate > &)> IceCandidatesCallback
Callback when candidates are gathered.
Definition ice.h:260
std::function< void(IceConnectionState)> IceConnectionStateCallback
Callback when connection state changes.
Definition ice.h:266
IceTransportProtocol
ICE candidate transport protocol.
Definition ice.h:65
std::function< void(const IceCandidatePair &)> IceSelectedPairCallback
Callback when ICE completes with selected pair.
Definition ice.h:272
constexpr uint32_t ICE_PRIORITY_SRFLX
Default ICE candidate priority for server-reflexive candidates
Definition ice.h:37
constexpr int ICE_CHECK_TIMEOUT_MS
Connectivity check timeout (ms)
Definition ice.h:43
constexpr int ICE_CHECK_MAX_RETRIES
Maximum connectivity check retries.
Definition ice.h:46
constexpr uint16_t STUN_DEFAULT_PORT
Default STUN port.
Definition stun.h:37
IceConnectionState
ICE connection state.
Definition ice.h:73
@ Closed
ICE agent closed.
@ Completed
ICE processing complete.
@ Checking
Performing connectivity checks.
@ Connected
At least one valid pair found.
@ Gathering
Gathering candidates.
@ Failed
ICE processing failed.
@ Disconnected
Connection lost.
int socket_t
Definition socket.h:22
#define INVALID_SOCKET_VALUE
Definition socket.h:23
ICE candidate pair.
Definition ice.h:167
int check_count
Number of checks performed.
Definition ice.h:173
std::string key() const
Get pair key for deduplication.
Definition ice.h:189
bool nominated
Nominated for use.
Definition ice.h:172
std::chrono::steady_clock::time_point last_check
Definition ice.h:174
IceCandidate local
Definition ice.h:168
static uint64_t compute_priority(uint32_t controlling_priority, uint32_t controlled_priority, bool is_controlling)
Compute pair priority (RFC 5245 Section 5.7.2)
IceCandidate remote
Definition ice.h:169
uint64_t priority
Pair priority.
Definition ice.h:171
IceCandidatePairState state
Definition ice.h:170
ICE candidate.
Definition ice.h:96
uint16_t port
Port number.
Definition ice.h:103
static std::string generate_foundation(IceCandidateType type, const std::string &base_address, const std::string &server_address="")
Generate foundation string.
std::string address
IP address.
Definition ice.h:102
std::string type_string() const
Get candidate type as string.
uint32_t component_id
Component ID (typically 1 for RTP)
Definition ice.h:99
std::string address_string() const
Get address:port string.
Definition ice.h:143
IceCandidateType type
Definition ice.h:97
std::string foundation
Unique identifier for candidate.
Definition ice.h:98
static uint32_t compute_priority(IceCandidateType type, uint32_t local_preference=65535, uint32_t component_id=1)
Compute candidate priority (RFC 5245 Section 4.1.2.1)
uint32_t priority
Candidate priority.
Definition ice.h:101
std::string to_sdp_attribute() const
Format candidate as SDP attribute string (a=candidate:...)
IceTransportProtocol transport
Definition ice.h:100
std::string related_address
Related address (for srflx/relay)
Definition ice.h:104
uint16_t related_port
Related port.
Definition ice.h:105
bool operator==(const IceCandidate &other) const
Definition ice.h:147
static std::optional< IceCandidate > from_sdp_attribute(const std::string &sdp)
Parse candidate from SDP attribute string.
ICE configuration.
Definition ice.h:226
bool gather_srflx_candidates
Gather server-reflexive candidates.
Definition ice.h:229
void add_turn_server(const std::string &host, uint16_t port, const std::string &username, const std::string &password)
Add a TURN server with credentials.
Definition ice.h:248
bool gather_host_candidates
Gather host candidates.
Definition ice.h:228
int check_max_retries
Max connectivity check retries.
Definition ice.h:233
std::string software
Software attribute.
Definition ice.h:234
int gathering_timeout_ms
Candidate gathering timeout.
Definition ice.h:231
void add_stun_server(const std::string &host, uint16_t port=STUN_DEFAULT_PORT)
Add a STUN server.
Definition ice.h:241
bool gather_relay_candidates
Gather relay candidates (requires TURN)
Definition ice.h:230
std::vector< IceServer > ice_servers
STUN/TURN servers.
Definition ice.h:227
int check_timeout_ms
Connectivity check timeout.
Definition ice.h:232
STUN/TURN server configuration.
Definition ice.h:197
std::string password
Password/credential (for TURN)
Definition ice.h:200
std::string url
Server URL (stun:host:port or turn:host:port)
Definition ice.h:198
bool is_stun() const
Check if this is a STUN server.
Definition ice.h:210
IceServer(const std::string &u, const std::string &user, const std::string &pass)
Definition ice.h:204
std::string username
Username (for TURN)
Definition ice.h:199
IceServer(const std::string &u)
Definition ice.h:203
bool parse_url(std::string &host, uint16_t &port) const
Parse host and port from URL.
bool is_turn() const
Check if this is a TURN server.
Definition ice.h:215
STUN (Session Traversal Utilities for NAT) Protocol Implementation.