1 /*! \file    ice.h
2  * \author   Lorenzo Miniero <lorenzo@meetecho.com>
3  * \copyright GNU General Public License v3
4  * \brief    ICE/STUN/TURN processing (headers)
5  * \details  Implementation (based on libnice) of the ICE process. The
6  * code handles the whole ICE process, from the gathering of candidates
7  * to the final setup of a virtual channel RTP and RTCP can be transported
8  * on. Incoming RTP and RTCP packets from peers are relayed to the associated
9  * plugins by means of the incoming_rtp and incoming_rtcp callbacks. Packets
10  * to be sent to peers are relayed by peers invoking the relay_rtp and
11  * relay_rtcp core callbacks instead.
12  *
13  * \ingroup protocols
14  * \ref protocols
15  */
16 
17 #ifndef JANUS_ICE_H
18 #define JANUS_ICE_H
19 
20 #include <glib.h>
21 #include <agent.h>
22 
23 #include "sdp.h"
24 #include "dtls.h"
25 #include "sctp.h"
26 #include "rtcp.h"
27 #include "text2pcap.h"
28 #include "utils.h"
29 #include "ip-utils.h"
30 #include "refcount.h"
31 #include "plugins/plugin.h"
32 
33 
34 /*! \brief ICE stuff initialization
35  * @param[in] ice_lite Whether the ICE Lite mode should be enabled or not
36  * @param[in] ice_tcp Whether ICE-TCP support should be enabled or not (only libnice >= 0.1.8, currently broken)
37  * @param[in] full_trickle Whether full-trickle must be used (instead of half-trickle)
38  * @param[in] ignore_mdns Whether mDNS candidates should be ignored, instead of resolved
39  * @param[in] ipv6 Whether IPv6 candidates must be negotiated or not
40  * @param[in] ipv6_linklocal Whether IPv6 link-local candidates should be gathered
41  * @param[in] rtp_min_port Minimum port to use for RTP/RTCP, if a range is to be used
42  * @param[in] rtp_max_port Maximum port to use for RTP/RTCP, if a range is to be used */
43 void janus_ice_init(gboolean ice_lite, gboolean ice_tcp, gboolean full_trickle, gboolean ignore_mdns,
44 	gboolean ipv6, gboolean ipv6_linklocal, uint16_t rtp_min_port, uint16_t rtp_max_port);
45 /*! \brief ICE stuff de-initialization */
46 void janus_ice_deinit(void);
47 /*! \brief Method to check whether a STUN server is reachable
48  * @param[in] addr Address of the STUN server as a janus_network_address instance
49  * @param[in] port Port of the STUN server
50  * @param[in] local_port Local port to bind to (0 means random choice)
51  * @param[out] public_addr Public address returned by the STUN server as a janus_network_address instance
52  * @param[out] public_port Public port returned by the STUN server
53  * @returns 0 in case of success, a negative integer on errors */
54 int janus_ice_test_stun_server(janus_network_address *addr, uint16_t port, uint16_t local_port, janus_network_address *public_addr, uint16_t *public_port);
55 /*! \brief Method to force Janus to use a STUN server when gathering candidates
56  * @param[in] stun_server STUN server address to use
57  * @param[in] stun_port STUN port to use
58  * @returns 0 in case of success, a negative integer on errors */
59 int janus_ice_set_stun_server(gchar *stun_server, uint16_t stun_port);
60 /*! \brief Method to force Janus to use a TURN server when gathering candidates
61  * @param[in] turn_server TURN server address to use
62  * @param[in] turn_port TURN port to use
63  * @param[in] turn_type Relay type (udp, tcp or tls)
64  * @param[in] turn_user TURN username, if needed
65  * @param[in] turn_pwd TURN password, if needed
66  * @returns 0 in case of success, a negative integer on errors */
67 int janus_ice_set_turn_server(gchar *turn_server, uint16_t turn_port, gchar *turn_type, gchar *turn_user, gchar *turn_pwd);
68 /*! \brief Method to force Janus to contact a TURN REST API server to get a TURN service to use when gathering candidates.
69  * The TURN REST API takes precedence over any static credential passed via janus_ice_set_turn_server
70  * @note Requires libcurl to be available, and a working TURN REST API backend (see turnrest.h)
71  * @param[in] api_server TURN REST API backend (NULL to disable the API)
72  * @param[in] api_key API key to use, if required
73  * @param[in] api_method HTTP method to use (POST by default)
74  * @param[in] api_timeout total timeout for HTTP method in seconds
75  * @returns 0 in case of success, a negative integer on errors */
76 int janus_ice_set_turn_rest_api(gchar *api_server, gchar *api_key, gchar *api_method, uint api_timeout);
77 /*! \brief Method to get the STUN server IP address
78  * @returns The currently used STUN server IP address, if available, or NULL if not */
79 char *janus_ice_get_stun_server(void);
80 /*! \brief Method to get the STUN server port
81  * @returns The currently used STUN server port, if available, or 0 if not */
82 uint16_t janus_ice_get_stun_port(void);
83 /*! \brief Method to get the TURN server IP address
84  * @returns The currently used TURN server IP address, if available, or NULL if not */
85 char *janus_ice_get_turn_server(void);
86 /*! \brief Method to get the TURN server port
87  * @returns The currently used TURN server port, if available, or 0 if not */
88 uint16_t janus_ice_get_turn_port(void);
89 /*! \brief Method to get the specified TURN REST API backend, if any
90  * @returns The currently specified  TURN REST API backend, if available, or NULL if not */
91 char *janus_ice_get_turn_rest_api(void);
92 /*! \brief Method to enable applications to force Janus to use TURN */
93 void janus_ice_allow_force_relay(void);
94 /*! \brief Method to check whether applications are allowed to force Janus to use TURN
95  * @returns TRUE if they're allowed, FALSE otherwise */
96 gboolean janus_ice_is_force_relay_allowed(void);
97 /*! \brief Helper method to force Janus to overwrite all host candidates with the public IP
98  * @param[in] keep_private_host Whether we should keep the original private host as a separate candidate, or replace it */
99 void janus_ice_enable_nat_1_1(gboolean keep_private_host);
100 /*! \brief Method to add an interface/IP to the enforce list for ICE (that is, only gather candidates from these and ignore the others)
101  * \note This method is especially useful to speed up the ICE gathering process on the server: in fact,
102  * if you know in advance which interface must be used (e.g., the main interface connected to the internet),
103  * adding it to the enforce list will prevent libnice from gathering candidates from other interfaces.
104  * If you're interested in excluding interfaces explicitly, instead, check janus_ice_ignore_interface.
105  * @param[in] ip Interface/IP to enforce (e.g., 192.168. or eth0) */
106 void janus_ice_enforce_interface(const char *ip);
107 /*! \brief Method to check whether an interface is currently in the enforce list for ICE (that is, won't have candidates)
108  * @param[in] ip Interface/IP to check (e.g., 192.168.244.1 or eth1)
109  * @returns true if the interface/IP is in the enforce list, false otherwise */
110 gboolean janus_ice_is_enforced(const char *ip);
111 /*! \brief Method to add an interface/IP to the ignore list for ICE (that is, don't gather candidates)
112  * \note This method is especially useful to speed up the ICE gathering process on the server: in fact,
113  * if you know in advance an interface is not going to be used (e.g., one of those created by VMware),
114  * adding it to the ignore list will prevent libnice from gathering a candidate for it.
115  * Unlike the enforce list, the ignore list also accepts IP addresses, partial or complete.
116  * If you're interested in only using specific interfaces, instead, check janus_ice_enforce_interface.
117  * @param[in] ip Interface/IP to ignore (e.g., 192.168. or eth1) */
118 void janus_ice_ignore_interface(const char *ip);
119 /*! \brief Method to check whether an interface/IP is currently in the ignore list for ICE (that is, won't have candidates)
120  * @param[in] ip Interface/IP to check (e.g., 192.168.244.1 or eth1)
121  * @returns true if the interface/IP is in the ignore list, false otherwise */
122 gboolean janus_ice_is_ignored(const char *ip);
123 /*! \brief Method to check whether ICE Lite mode is enabled or not (still WIP)
124  * @returns true if ICE-TCP support is enabled/supported, false otherwise */
125 gboolean janus_ice_is_ice_lite_enabled(void);
126 /*! \brief Method to check whether ICE-TCP support is enabled/supported or not (still WIP)
127  * @returns true if ICE-TCP support is enabled/supported, false otherwise */
128 gboolean janus_ice_is_ice_tcp_enabled(void);
129 /*! \brief Method to check whether full-trickle support is enabled or not
130  * @returns true if full-trickle support is enabled, false otherwise */
131 gboolean janus_ice_is_full_trickle_enabled(void);
132 /*! \brief Method to check whether mDNS resolution is enabled or not
133  * @returns true if mDNS resolution is enabled, false otherwise */
134 gboolean janus_ice_is_mdns_enabled(void);
135 /*! \brief Method to check whether IPv6 candidates are enabled/supported or not
136  * @returns true if IPv6 candidates are enabled/supported, false otherwise */
137 gboolean janus_ice_is_ipv6_enabled(void);
138 /*! \brief Method to check whether IPv6 link-local candidates will be gathered or not
139  * \note This obviously only makes sense if IPv6 support is enabled in general
140  * @returns true if IPv6 link-local candidates will be gathered, false otherwise */
141 gboolean janus_ice_is_ipv6_linklocal_enabled(void);
142 #ifdef HAVE_ICE_NOMINATION
143 /*! \brief Method to configure the ICE nomination mode (regular or aggressive)
144  * @param[in] nomination The ICE nomination mode (regular or aggressive) */
145 void janus_ice_set_nomination_mode(const char *nomination);
146 /*! \brief Method to return a string description of the configured ICE nomination mode
147  * @returns "regular" or "aggressive" */
148 const char *janus_ice_get_nomination_mode(void);
149 #endif
150 /*! \brief Method to enable/disable connectivity checks as keepalives for PeerConnections.
151  * \note The main rationale behind this setting is provided in the libnice documentation:
152  * https://libnice.freedesktop.org/libnice/NiceAgent.html#NiceAgent--keepalive-conncheck
153  * @param[in] enabled Whether the functionality should be enabled or disabled */
154 void janus_ice_set_keepalive_conncheck_enabled(gboolean enabled);
155 /*! \brief Method to check whether connectivity checks will be used as keepalives
156  * @returns true if enabled, false (default) otherwise */
157 gboolean janus_ice_is_keepalive_conncheck_enabled(void);
158 /*! \brief Method to modify the min NACK value (i.e., the minimum time window of packets per handle to store for retransmissions)
159  * @param[in] mnq The new min NACK value */
160 void janus_set_min_nack_queue(uint16_t mnq);
161 /*! \brief Method to get the current min NACK value (i.e., the minimum time window of packets per handle to store for retransmissions)
162  * @returns The current min NACK value */
163 uint16_t janus_get_min_nack_queue(void);
164 /*! \brief Method to enable/disable the NACK optimizations on outgoing keyframes: when
165  * enabled, the NACK buffer for a PeerConnection is cleaned any time Janus sends a
166  * keyframe, as any missing packet won't be needed since the keyframe will allow the
167  * media recipient to still restore a complete image anyway. Since this optimization
168  * seems to cause some issues in some edge cases, it's disabled by default.
169  * @param[in] optimize Whether the optimization should be enabled or disabled */
170 void janus_set_nack_optimizations_enabled(gboolean optimize);
171 /*! \brief Method to check whether NACK optimizations on outgoing keyframes are enabled or not
172  * @returns optimize if optimizations are enabled, false otherwise */
173 gboolean janus_is_nack_optimizations_enabled(void);
174 /*! \brief Method to modify the no-media event timer (i.e., the number of seconds where no media arrives before Janus notifies this)
175  * @param[in] timer The new timer value, in seconds */
176 void janus_set_no_media_timer(uint timer);
177 /*! \brief Method to get the current no-media event timer (see above)
178  * @returns The current no-media event timer */
179 uint janus_get_no_media_timer(void);
180 /*! \brief Method to modify the slowlink-threshold property (i.e., the number of lost packets per seconds that should trigger a slow-link event)
181  * @param[in] packets The new value, in lost packets per seconds */
182 void janus_set_slowlink_threshold(uint packets);
183 /*! \brief Method to get the current slowlink-threshold value (see above)
184  * @returns The current slowlink-threshold value */
185 uint janus_get_slowlink_threshold(void);
186 /*! \brief Method to modify the TWCC feedback period (i.e., how often TWCC feedback is sent back to media senders)
187  * @param[in] period The new period value, in milliseconds */
188 void janus_set_twcc_period(uint period);
189 /*! \brief Method to get the current TWCC period (see above)
190  * @returns The current TWCC period */
191 uint janus_get_twcc_period(void);
192 /*! \brief Method to modify the DSCP value to set, which is disabled by default
193  * @param[in] dscp The new DSCP value (0 to disable) */
194 void janus_set_dscp(int dscp);
195 /*! \brief Method to get the current DSCP value (see above)
196  * @returns The current DSCP value (0 if disabled) */
197 int janus_get_dscp(void);
198 /*! \brief Method to modify the event handler statistics period (i.e., the number of seconds that should pass before Janus notifies event handlers about media statistics for a PeerConnection)
199  * @param[in] period The new period value, in seconds */
200 void janus_ice_set_event_stats_period(int period);
201 /*! \brief Method to get the current event handler statistics period (see above)
202  * @returns The current event handler stats period */
203 int janus_ice_get_event_stats_period(void);
204 
205 /*! \brief Method to define wether the media stats shall be dispatched in one event (true) or in dedicated single events (false - default)
206  * @param[in] combine_media_stats_to_one_event true to combine media statistics in on event or false to send dedicated events */
207 void janus_ice_event_set_combine_media_stats(gboolean combine_media_stats_to_one_event);
208 /*! \brief Method to retrieve wether media statistic events shall be dispatched combined or in single events
209  * @returns true to combine events */
210 gboolean janus_ice_event_get_combine_media_stats(void);
211 
212 /*! \brief Method to check whether libnice debugging has been enabled (http://nice.freedesktop.org/libnice/libnice-Debug-messages.html)
213  * @returns True if libnice debugging is enabled, FALSE otherwise */
214 gboolean janus_ice_is_ice_debugging_enabled(void);
215 /*! \brief Method to enable libnice debugging (http://nice.freedesktop.org/libnice/libnice-Debug-messages.html) */
216 void janus_ice_debugging_enable(void);
217 /*! \brief Method to disable libnice debugging (the default) */
218 void janus_ice_debugging_disable(void);
219 /*! \brief Method to enable opaque ID in Janus API responses/events */
220 void janus_enable_opaqueid_in_api(void);
221 /*! \brief Method to check whether opaque ID have to be added to Janus API responses/events
222  * @returns TRUE if they need to be present, FALSE otherwise */
223 gboolean janus_is_opaqueid_in_api_enabled(void);
224 
225 
226 /*! \brief Helper method to get a string representation of a libnice ICE state
227  * @param[in] state The libnice ICE state
228  * @returns A string representation of the libnice ICE state */
229 const gchar *janus_get_ice_state_name(gint state);
230 
231 
232 /*! \brief Janus ICE handle/session */
233 typedef struct janus_ice_handle janus_ice_handle;
234 /*! \brief Janus ICE stream */
235 typedef struct janus_ice_stream janus_ice_stream;
236 /*! \brief Janus ICE component */
237 typedef struct janus_ice_component janus_ice_component;
238 /*! \brief Helper to handle pending trickle candidates (e.g., when we're still waiting for an offer) */
239 typedef struct janus_ice_trickle janus_ice_trickle;
240 
241 #define JANUS_ICE_HANDLE_WEBRTC_PROCESSING_OFFER	(1 << 0)
242 #define JANUS_ICE_HANDLE_WEBRTC_START				(1 << 1)
243 #define JANUS_ICE_HANDLE_WEBRTC_READY				(1 << 2)
244 #define JANUS_ICE_HANDLE_WEBRTC_STOP				(1 << 3)
245 #define JANUS_ICE_HANDLE_WEBRTC_ALERT				(1 << 4)
246 #define JANUS_ICE_HANDLE_WEBRTC_NEGOTIATED			(1 << 5)
247 #define JANUS_ICE_HANDLE_WEBRTC_TRICKLE				(1 << 7)
248 #define JANUS_ICE_HANDLE_WEBRTC_ALL_TRICKLES		(1 << 8)
249 #define JANUS_ICE_HANDLE_WEBRTC_TRICKLE_SYNCED		(1 << 9)
250 #define JANUS_ICE_HANDLE_WEBRTC_DATA_CHANNELS		(1 << 10)
251 #define JANUS_ICE_HANDLE_WEBRTC_CLEANING			(1 << 11)
252 #define JANUS_ICE_HANDLE_WEBRTC_HAS_AUDIO			(1 << 12)
253 #define JANUS_ICE_HANDLE_WEBRTC_HAS_VIDEO			(1 << 13)
254 #define JANUS_ICE_HANDLE_WEBRTC_GOT_OFFER			(1 << 14)
255 #define JANUS_ICE_HANDLE_WEBRTC_GOT_ANSWER			(1 << 15)
256 #define JANUS_ICE_HANDLE_WEBRTC_HAS_AGENT			(1 << 16)
257 #define JANUS_ICE_HANDLE_WEBRTC_ICE_RESTART			(1 << 17)
258 #define JANUS_ICE_HANDLE_WEBRTC_RESEND_TRICKLES		(1 << 18)
259 #define JANUS_ICE_HANDLE_WEBRTC_RFC4588_RTX			(1 << 19)
260 #define JANUS_ICE_HANDLE_WEBRTC_NEW_DATACHAN_SDP	(1 << 20)
261 #define JANUS_ICE_HANDLE_WEBRTC_E2EE				(1 << 21)
262 
263 
264 /*! \brief Janus media statistics
265  * \note To improve with more stuff */
266 typedef struct janus_ice_stats_info {
267 	/*! \brief Packets sent or received */
268 	guint32 packets;
269 	/*! \brief Bytes sent or received */
270 	guint64 bytes;
271 	/*! \brief Bytes sent or received in the last second */
272 	guint32 bytes_lastsec, bytes_lastsec_temp;
273 	/*! \brief Time we last updated the last second counter */
274 	gint64 updated;
275 	/*! \brief Whether or not we notified about lastsec issues already */
276 	gboolean notified_lastsec;
277 	/*! \brief Number of NACKs sent or received */
278 	guint32 nacks;
279 } janus_ice_stats_info;
280 
281 /*! \brief Janus media statistics container
282  * \note To improve with more stuff */
283 typedef struct janus_ice_stats {
284 	/*! \brief Audio info */
285 	janus_ice_stats_info audio;
286 	/*! \brief Video info (considering we may be simulcasting) */
287 	janus_ice_stats_info video[3];
288 	/*! \brief Data info */
289 	janus_ice_stats_info data;
290 	/*! \brief Last known count of lost audio packets (for slow_link) */
291 	guint sl_lost_count_audio;
292 	/*! \brief Last known count of lost video packets (for slow_link) */
293 	guint sl_lost_count_video;
294 } janus_ice_stats;
295 
296 /*! \brief Quick helper method to notify a WebRTC hangup through the Janus API
297  * @param handle The janus_ice_handle instance this event refers to
298  * @param reason A description of why this happened */
299 void janus_ice_notify_hangup(janus_ice_handle *handle, const char *reason);
300 
301 
302 /*! \brief Quick helper method to check if a plugin session associated with a Janus handle is still valid
303  * @param plugin_session The janus_plugin_session instance to validate
304  * @returns true if the plugin session is valid, false otherwise */
305 gboolean janus_plugin_session_is_alive(janus_plugin_session *plugin_session);
306 
307 
308 /*! \brief A helper struct for determining when to send NACKs */
309 typedef struct janus_seq_info {
310 	gint64 ts;
311 	guint16 seq;
312 	guint16 state;
313 	struct janus_seq_info *next;
314 	struct janus_seq_info *prev;
315 } janus_seq_info;
316 void janus_seq_list_free(janus_seq_info **head);
317 enum {
318 	SEQ_MISSING,
319 	SEQ_NACKED,
320 	SEQ_GIVEUP,
321 	SEQ_RECVED
322 };
323 
324 
325 /*! \brief Janus ICE handle */
326 struct janus_ice_handle {
327 	/*! \brief Opaque pointer to the core/peer session */
328 	void *session;
329 	/*! \brief Handle identifier, guaranteed to be non-zero */
330 	guint64 handle_id;
331 	/*! \brief Opaque identifier, e.g., to provide inter-handle relationships to external tools */
332 	char *opaque_id;
333 	/*! \brief Token that was used to attach the handle, if required */
334 	char *token;
335 	/*! \brief Monotonic time of when the handle has been created */
336 	gint64 created;
337 	/*! \brief Opaque application (plugin) pointer */
338 	void *app;
339 	/*! \brief Opaque core/plugin session pointer */
340 	janus_plugin_session *app_handle;
341 	/*! \brief Mask of WebRTC-related flags for this handle */
342 	janus_flags webrtc_flags;
343 	/*! \brief Number of gathered candidates */
344 	gint cdone;
345 	/*! \brief GLib context for the handle and libnice */
346 	GMainContext *mainctx;
347 	/*! \brief GLib loop for the handle and libnice */
348 	GMainLoop *mainloop;
349 	/*! \brief GLib thread for the handle and libnice */
350 	GThread *thread;
351 	/*! \brief GLib sources for outgoing traffic, recurring RTCP, and stats (and optionally TWCC) */
352 	GSource *rtp_source, *rtcp_source, *stats_source, *twcc_source;
353 	/*! \brief libnice ICE agent */
354 	NiceAgent *agent;
355 	/*! \brief Monotonic time of when the ICE agent has been created */
356 	gint64 agent_created;
357 	/*! \brief ICE role (controlling or controlled) */
358 	gboolean controlling;
359 	/*! \brief Audio mid (media ID) */
360 	gchar *audio_mid;
361 	/*! \brief Video mid (media ID) */
362 	gchar *video_mid;
363 	/*! \brief Data channel mid (media ID) */
364 	gchar *data_mid;
365 	/*! \brief Main mid (will be a pointer to one of the above) */
366 	gchar *stream_mid;
367 	/*! \brief ICE Stream ID */
368 	guint stream_id;
369 	/*! \brief ICE stream */
370 	janus_ice_stream *stream;
371 	/*! \brief RTP profile set by caller (so that we can match it) */
372 	gchar *rtp_profile;
373 	/*! \brief SDP generated locally (just for debugging purposes) */
374 	gchar *local_sdp;
375 	/*! \brief SDP received by the peer (just for debugging purposes) */
376 	gchar *remote_sdp;
377 	/*! \brief Reason this handle has been hung up*/
378 	const gchar *hangup_reason;
379 	/*! \brief List of pending trickle candidates (those we received before getting the JSEP offer) */
380 	GList *pending_trickles;
381 	/*! \brief Queue of remote candidates that still need to be processed */
382 	GAsyncQueue *queued_candidates;
383 	/*! \brief Queue of events in the loop and outgoing packets to send */
384 	GAsyncQueue *queued_packets;
385 	/*! \brief Count of the recent SRTP replay errors, in order to avoid spamming the logs */
386 	guint srtp_errors_count;
387 	/*! \brief Count of the recent SRTP replay errors, in order to avoid spamming the logs */
388 	gint last_srtp_error, last_srtp_summary;
389 	/*! \brief Count of how many seconds passed since the last stats passed to event handlers */
390 	gint last_event_stats;
391 	/*! \brief Flag to decide whether or not packets need to be dumped to a text2pcap file */
392 	volatile gint dump_packets;
393 	/*! \brief In case this session must be saved to text2pcap, the instance to dump packets to */
394 	janus_text2pcap *text2pcap;
395 	/*! \brief Mutex to lock/unlock the ICE session */
396 	janus_mutex mutex;
397 	/*! \brief Whether a close_pc was requested recently on the PeerConnection */
398 	volatile gint closepc;
399 	/*! \brief Atomic flag to check if this instance has been destroyed */
400 	volatile gint destroyed;
401 	/*! \brief Reference counter for this instance */
402 	janus_refcount ref;
403 };
404 
405 /*! \brief Janus ICE stream */
406 struct janus_ice_stream {
407 	/*! \brief Janus ICE handle this stream belongs to */
408 	janus_ice_handle *handle;
409 	/*! \brief libnice ICE stream ID */
410 	guint stream_id;
411 	/*! \brief Whether this stream is ready to be used */
412 	gint cdone:1;
413 	/*! \brief Audio SSRC of the server for this stream */
414 	guint32 audio_ssrc;
415 	/*! \brief Video SSRC of the server for this stream */
416 	guint32 video_ssrc;
417 	/*! \brief Video retransmission SSRC of the peer for this stream */
418 	guint32 video_ssrc_rtx;
419 	/*! \brief Audio SSRC of the peer for this stream */
420 	guint32 audio_ssrc_peer, audio_ssrc_peer_new, audio_ssrc_peer_orig;
421 	/*! \brief Video SSRC(s) of the peer for this stream (may be simulcasting) */
422 	guint32 video_ssrc_peer[3], video_ssrc_peer_new[3], video_ssrc_peer_orig[3], video_ssrc_peer_temp;
423 	/*! \brief Video retransmissions SSRC(s) of the peer for this stream */
424 	guint32 video_ssrc_peer_rtx[3], video_ssrc_peer_rtx_new[3], video_ssrc_peer_rtx_orig[3];
425 	/*! \brief Array of RTP Stream IDs (for Firefox simulcasting, if enabled) */
426 	char *rid[3];
427 	/*! \brief Whether the order of the rids in the SDP will be h-m-l (TRUE) or l-m-h (FALSE) */
428 	gboolean rids_hml;
429 	/*! \brief Whether we should use the legacy simulcast syntax (a=simulcast:recv rid=..) or the proper one (a=simulcast:recv ..) */
430 	gboolean legacy_rid;
431 	/*! \brief RTP switching context(s) in case of renegotiations (audio+video and/or simulcast) */
432 	janus_rtp_switching_context rtp_ctx[3];
433 	/*! \brief List of payload types we can expect for audio */
434 	GList *audio_payload_types;
435 	/*! \brief List of payload types we can expect for video */
436 	GList *video_payload_types;
437 	/*! \brief Mapping of rtx payload types to actual media-related packet types */
438 	GHashTable *rtx_payload_types;
439 	/*! \brief Mapping of payload types to their clock rates, as advertised in the SDP */
440 	GHashTable *clock_rates;
441 	/*! \brief RTP payload types of this stream */
442 	gint audio_payload_type, video_payload_type, video_rtx_payload_type;
443 	/*! \brief Codecs used by this stream */
444 	char *audio_codec, *video_codec;
445 	/*! \brief Pointer to function to check if a packet is a keyframe (depends on negotiated codec) */
446 	gboolean (* video_is_keyframe)(const char* buffer, int len);
447 	/*! \brief Media direction */
448 	gboolean audio_send, audio_recv, video_send, video_recv;
449 	/*! \brief RTCP context for the audio stream */
450 	janus_rtcp_context *audio_rtcp_ctx;
451 	/*! \brief RTCP context(s) for the video stream (may be simulcasting) */
452 	janus_rtcp_context *video_rtcp_ctx[3];
453 	/*! \brief Latest REMB feedback we received */
454 	uint32_t remb_bitrate;
455 	/*! \brief Size of the NACK queue (in ms), dynamically updated per the RTT */
456 	uint16_t nack_queue_ms;
457 	/*! \brief Map(s) of the NACKed packets (to track retransmissions and avoid duplicates) */
458 	GHashTable *rtx_nacked[3];
459 	/*! \brief Map of the pending NACKed cleanup callback */
460 	GHashTable *pending_nacked_cleanup;
461 	/*! \brief First received audio NTP timestamp */
462 	gint64 audio_first_ntp_ts;
463 	/*! \brief First received audio RTP timestamp */
464 	guint32 audio_first_rtp_ts;
465 	/*! \brief First received video NTP timestamp (for all simulcast video streams) */
466 	gint64 video_first_ntp_ts[3];
467 	/*! \brief First received video NTP RTP timestamp (for all simulcast video streams) */
468 	guint32 video_first_rtp_ts[3];
469 	/*! \brief Last sent audio NTP timestamp */
470 	gint64 audio_last_ntp_ts;
471 	/*! \brief Last sent audio RTP timestamp */
472 	guint32 audio_last_rtp_ts;
473 	/*! \brief Last sent video NTP timestamp */
474 	gint64 video_last_ntp_ts;
475 	/*! \brief Last sent video RTP timestamp */
476 	guint32 video_last_rtp_ts;
477 	/*! \brief SDES mid RTP extension ID */
478 	gint mid_ext_id;
479 	/*! \brief RTP Stream extension ID, and the related rtx one */
480 	gint rid_ext_id, ridrtx_ext_id;
481 	/*! \brief Audio levels extension ID */
482 	gint audiolevel_ext_id;
483 	/*! \brief Video orientation extension ID */
484 	gint videoorientation_ext_id;
485 	/*! \brief Absolute Send Time ext ID */
486 	gint abs_send_time_ext_id;
487 	/*! \brief Whether we do transport wide cc for video */
488 	gboolean do_transport_wide_cc;
489 	/*! \brief Transport wide cc rtp ext ID */
490 	gint transport_wide_cc_ext_id;
491 	/*! \brief Last sent transport wide seq num */
492 	guint16 transport_wide_cc_out_seq_num;
493 	/*! \brief Last received transport wide seq num */
494 	guint32 transport_wide_cc_last_seq_num;
495 	/*! \brief Last transport wide seq num sent on feedback */
496 	guint32 transport_wide_cc_last_feedback_seq_num;
497 	/*! \brief Transport wide cc transport seq num wrap cycles */
498 	guint16 transport_wide_cc_cycles;
499 	/*! \brief Transport wide cc rtp ext ID */
500 	guint transport_wide_cc_feedback_count;
501 	/*! \brief GLib list of transport wide cc stats in reverse received order */
502 	GSList *transport_wide_received_seq_nums;
503 	/*! \brief DTLS role of the server for this stream */
504 	janus_dtls_role dtls_role;
505 	/*! \brief Hashing algorhitm used by the peer for the DTLS certificate (e.g., "SHA-256") */
506 	gchar *remote_hashing;
507 	/*! \brief Hashed fingerprint of the peer's certificate, as parsed in SDP */
508 	gchar *remote_fingerprint;
509 	/*! \brief The ICE username for this stream */
510 	gchar *ruser;
511 	/*! \brief The ICE password for this stream */
512 	gchar *rpass;
513 	/*! \brief GLib hash table of components (IDs are the keys) */
514 	GHashTable *components;
515 	/*! \brief ICE component */
516 	janus_ice_component *component;
517 	/*! \brief Helper flag to avoid flooding the console with the same error all over again */
518 	gboolean noerrorlog;
519 	/*! \brief Mutex to lock/unlock this stream */
520 	janus_mutex mutex;
521 	/*! \brief Atomic flag to check if this instance has been destroyed */
522 	volatile gint destroyed;
523 	/*! \brief Reference counter for this instance */
524 	janus_refcount ref;
525 };
526 
527 #define LAST_SEQS_MAX_LEN 160
528 /*! \brief Janus ICE component */
529 struct janus_ice_component {
530 	/*! \brief Janus ICE stream this component belongs to */
531 	janus_ice_stream *stream;
532 	/*! \brief libnice ICE stream ID */
533 	guint stream_id;
534 	/*! \brief libnice ICE component ID */
535 	guint component_id;
536 	/*! \brief libnice ICE component state */
537 	guint state;
538 	/*! \brief Monotonic time of when this component has successfully connected */
539 	gint64 component_connected;
540 	/*! \brief GLib list of libnice remote candidates for this component */
541 	GSList *candidates;
542 	/*! \brief GLib list of local candidates for this component (summary) */
543 	GSList *local_candidates;
544 	/*! \brief GLib list of remote candidates for this component (summary) */
545 	GSList *remote_candidates;
546 	/*! \brief String representation of the selected pair as notified by libnice (foundations) */
547 	gchar *selected_pair;
548 	/*! \brief Whether the setup of remote candidates for this component has started or not */
549 	gboolean process_started;
550 	/*! \brief Timer to check when we should consider ICE as failed */
551 	GSource *icestate_source;
552 	/*! \brief Time of when we first detected an ICE failed (we'll need this for the timer above) */
553 	gint64 icefailed_detected;
554 	/*! \brief Re-transmission timer for DTLS */
555 	GSource *dtlsrt_source;
556 	/*! \brief DTLS-SRTP stack */
557 	janus_dtls_srtp *dtls;
558 	/*! \brief Whether we should do NACKs (in or out) for audio */
559 	gboolean do_audio_nacks;
560 	/*! \brief Whether we should do NACKs (in or out) for video */
561 	gboolean do_video_nacks;
562 	/*! \brief List of previously sent janus_rtp_packet RTP packets, in case we receive NACKs */
563 	GQueue *audio_retransmit_buffer, *video_retransmit_buffer;
564 	/*! \brief HashTable of retransmittable sequence numbers, in case we receive NACKs */
565 	GHashTable *audio_retransmit_seqs, *video_retransmit_seqs;
566 	/*! \brief Current sequence number for the RFC4588 rtx SSRC session */
567 	guint16 rtx_seq_number;
568 	/*! \brief Last time a log message about sending retransmits was printed */
569 	gint64 retransmit_log_ts;
570 	/*! \brief Number of retransmitted packets since last log message */
571 	guint retransmit_recent_cnt;
572 	/*! \brief Last time a log message about sending NACKs was printed */
573 	gint64 nack_sent_log_ts;
574 	/*! \brief Number of NACKs sent since last log message */
575 	guint nack_sent_recent_cnt;
576 	/*! \brief List of recently received audio sequence numbers (as a support to NACK generation) */
577 	janus_seq_info *last_seqs_audio;
578 	/*! \brief List of recently received video sequence numbers (as a support to NACK generation, for each simulcast SSRC) */
579 	janus_seq_info *last_seqs_video[3];
580 	/*! \brief Stats for incoming data (audio/video/data) */
581 	janus_ice_stats in_stats;
582 	/*! \brief Stats for outgoing data (audio/video/data) */
583 	janus_ice_stats out_stats;
584 	/*! \brief Helper flag to avoid flooding the console with the same error all over again */
585 	gboolean noerrorlog;
586 	/*! \brief Mutex to lock/unlock this component */
587 	janus_mutex mutex;
588 	/*! \brief Atomic flag to check if this instance has been destroyed */
589 	volatile gint destroyed;
590 	/*! \brief Reference counter for this instance */
591 	janus_refcount ref;
592 };
593 
594 /*! \brief Helper to handle pending trickle candidates (e.g., when we're still waiting for an offer) */
595 struct janus_ice_trickle {
596 	/*! \brief Janus ICE handle this trickle candidate belongs to */
597 	janus_ice_handle *handle;
598 	/*! \brief Monotonic time of when this trickle candidate has been received */
599 	gint64 received;
600 	/*! \brief Janus API transaction ID of the original trickle request */
601 	char *transaction;
602 	/*! \brief JSON object of the trickle candidate(s) */
603 	json_t *candidate;
604 };
605 
606 /** @name Janus ICE trickle candidates methods
607  */
608 ///@{
609 /*! \brief Helper method to allocate a janus_ice_trickle instance
610  * @param[in] transaction The Janus API ID of the original trickle request
611  * @param[in] candidate The trickle candidate, as a Jansson object
612  * @returns a pointer to the new instance, if successful, NULL otherwise */
613 janus_ice_trickle *janus_ice_trickle_new(const char *transaction, json_t *candidate);
614 /*! \brief Helper method to parse trickle candidates
615  * @param[in] handle The Janus ICE handle this candidate belongs to
616  * @param[in] candidate The trickle candidate to parse, as a Jansson object
617  * @param[in,out] error Error string describing the failure, if any
618  * @returns 0 in case of success, any code from apierror.h in case of failure */
619 gint janus_ice_trickle_parse(janus_ice_handle *handle, json_t *candidate, const char **error);
620 /*! \brief Helper method to destroy a janus_ice_trickle instance
621  * @param[in] trickle The janus_ice_trickle instance to destroy */
622 void janus_ice_trickle_destroy(janus_ice_trickle *trickle);
623 ///@}
624 
625 
626 /** @name Janus ICE handle methods
627  */
628 ///@{
629 /*! \brief Method to create a new Janus ICE handle
630  * @param[in] core_session The core/peer session this ICE handle will belong to
631  * @param[in] opaque_id The opaque identifier provided by the creator, if any (optional)
632  * @param[in] token The auth token provided by the creator, if any (optional)
633  * @returns The created Janus ICE handle if successful, NULL otherwise */
634 janus_ice_handle *janus_ice_handle_create(void *core_session, const char *opaque_id, const char *token);
635 /*! \brief Method to attach a Janus ICE handle to a plugin
636  * \details This method is very important, as it allows plugins to send/receive media (RTP/RTCP) to/from a WebRTC peer.
637  * @param[in] core_session The core/peer session this ICE handle belongs to
638  * @param[in] handle The Janus ICE handle
639  * @param[in] plugin The plugin the ICE handle needs to be attached to
640  * @param[in] loop_index In case static event loops are used, an indication on which loop to use for this handle
641  * (-1 will let the core pick one; in case API selection is disabled in the settings, this value is ignored)
642  * @returns 0 in case of success, a negative integer otherwise */
643 gint janus_ice_handle_attach_plugin(void *core_session, janus_ice_handle *handle, janus_plugin *plugin, int loop_index);
644 /*! \brief Method to destroy a Janus ICE handle
645  * @param[in] core_session The core/peer session this ICE handle belongs to
646  * @param[in] handle The Janus ICE handle to destroy
647  * @returns 0 in case of success, a negative integer otherwise */
648 gint janus_ice_handle_destroy(void *core_session, janus_ice_handle *handle);
649 /*! \brief Method to only hangup (e.g., DTLS alert) the WebRTC PeerConnection allocated by a Janus ICE handle
650  * @param[in] handle The Janus ICE handle instance managing the WebRTC PeerConnection to hangup
651  * @param[in] reason A description of why this happened */
652 void janus_ice_webrtc_hangup(janus_ice_handle *handle, const char *reason);
653 /*! \brief Method to only free resources related to a specific ICE stream allocated by a Janus ICE handle
654  * @param[in] stream The Janus ICE stream instance to free */
655 void janus_ice_stream_destroy(janus_ice_stream *stream);
656 /*! \brief Method to only free resources related to a specific ICE component allocated by a Janus ICE handle
657  * @param[in] component The Janus ICE component instance to free */
658 void janus_ice_component_destroy(janus_ice_component *component);
659 ///@}
660 
661 
662 /** @name Janus ICE media relaying callbacks
663  */
664 ///@{
665 /*! \brief Core RTP callback, called when a plugin has an RTP packet to send to a peer
666  * @param[in] handle The Janus ICE handle associated with the peer
667  * @param[in] packet The RTP packet to send */
668 void janus_ice_relay_rtp(janus_ice_handle *handle, janus_plugin_rtp *packet);
669 /*! \brief Core RTCP callback, called when a plugin has an RTCP message to send to a peer
670  * @param[in] handle The Janus ICE handle associated with the peer
671  * @param[in] packet The RTCP message to send */
672 void janus_ice_relay_rtcp(janus_ice_handle *handle, janus_plugin_rtcp *packet);
673 /*! \brief Core SCTP/DataChannel callback, called when a plugin has data to send to a peer
674  * @param[in] handle The Janus ICE handle associated with the peer
675  * @param[in] packet The message to send */
676 void janus_ice_relay_data(janus_ice_handle *handle, janus_plugin_data *packet);
677 /*! \brief Helper core callback, called when a plugin wants to send a RTCP PLI to a peer
678  * @param[in] handle The Janus ICE handle associated with the peer */
679 void janus_ice_send_pli(janus_ice_handle *handle);
680 /*! \brief Helper core callback, called when a plugin wants to send a RTCP REMB to a peer
681  * @param[in] handle The Janus ICE handle associated with the peer
682  * @param[in] bitrate The bitrate value to put in the REMB message */
683 void janus_ice_send_remb(janus_ice_handle *handle, uint32_t bitrate);
684 /*! \brief Plugin SCTP/DataChannel callback, called by the SCTP stack when when there's data for a plugin
685  * @param[in] handle The Janus ICE handle associated with the peer
686  * @param[in] label The label of the data channel the message is from
687  * @param[in] protocol The protocol of the data channel to use
688  * @param[in] textdata Whether the buffer is text (domstring) or binary data
689  * @param[in] buffer The message data (buffer)
690  * @param[in] length The buffer length */
691 void janus_ice_incoming_data(janus_ice_handle *handle, char *label, char *protocol, gboolean textdata, char *buffer, int length);
692 /*! \brief Core SCTP/DataChannel callback, called by the SCTP stack when when there's data to send.
693  * @param[in] handle The Janus ICE handle associated with the peer
694  * @param[in] buffer The message data (buffer)
695  * @param[in] length The buffer length */
696 void janus_ice_relay_sctp(janus_ice_handle *handle, char *buffer, int length);
697 /*! \brief Plugin SCTP/DataChannel callback, called by the SCTP stack when data can be written
698  * @param[in] handle The Janus ICE handle associated with the peer */
699 void janus_ice_notify_data_ready(janus_ice_handle *handle);
700 /*! \brief Core SDP callback, called by the SDP stack when a stream has been paused by a negotiation
701  * @param[in] handle The Janus ICE handle associated with the peer */
702 void janus_ice_notify_media_stopped(janus_ice_handle *handle);
703 ///@}
704 
705 
706 /** @name Janus ICE handle helpers
707  */
708 ///@{
709 /*! \brief Method to locally set up the ICE candidates (initialization and gathering)
710  * @param[in] handle The Janus ICE handle this method refers to
711  * @param[in] offer Whether this is for an OFFER or an ANSWER
712  * @param[in] audio Whether audio is enabled
713  * @param[in] video Whether video is enabled
714  * @param[in] data Whether SCTP data channels are enabled
715  * @param[in] trickle Whether ICE trickling is supported or not
716  * @returns 0 in case of success, a negative integer otherwise */
717 int janus_ice_setup_local(janus_ice_handle *handle, int offer, int audio, int video, int data, int trickle);
718 /*! \brief Method to add local candidates to a janus_sdp SDP object representation
719  * @param[in] handle The Janus ICE handle this method refers to
720  * @param[in] mline The Janus SDP m-line object to add candidates to
721  * @param[in] stream_id The stream ID of the candidate to add to the SDP
722  * @param[in] component_id The component ID of the candidate to add to the SDP */
723 void janus_ice_candidates_to_sdp(janus_ice_handle *handle, janus_sdp_mline *mline, guint stream_id, guint component_id);
724 /*! \brief Method to queue a remote candidate for processing
725  * @param[in] handle The Janus ICE handle this method refers to
726  * @param[in] c The remote NiceCandidate to process */
727 void janus_ice_add_remote_candidate(janus_ice_handle *handle, NiceCandidate *c);
728 /*! \brief Method to handle remote candidates and start the connectivity checks
729  * @param[in] handle The Janus ICE handle this method refers to
730  * @param[in] stream_id The stream ID of the candidate to add to the SDP
731  * @param[in] component_id The component ID of the candidate to add to the SDP */
732 void janus_ice_setup_remote_candidates(janus_ice_handle *handle, guint stream_id, guint component_id);
733 /*! \brief Callback to be notified when the DTLS handshake for a specific component has been completed
734  * \details This method also decides when to notify attached plugins about the availability of a reliable PeerConnection
735  * @param[in] handle The Janus ICE handle this callback refers to
736  * @param[in] component The Janus ICE component that is now ready to be used */
737 void janus_ice_dtls_handshake_done(janus_ice_handle *handle, janus_ice_component *component);
738 /*! \brief Method to restart ICE and the connectivity checks
739  * @param[in] handle The Janus ICE handle this method refers to */
740 void janus_ice_restart(janus_ice_handle *handle);
741 /*! \brief Method to resend all the existing candidates via trickle (e.g., after an ICE restart)
742  * @param[in] handle The Janus ICE handle this method refers to */
743 void janus_ice_resend_trickles(janus_ice_handle *handle);
744 ///@}
745 
746 
747 /*! \brief Method to configure the static event loops mechanism at startup
748  * @note Check the \c event_loops property in the \c janus.jcfg configuration
749  * for an explanation of this feature, and the possible impact on Janus and users
750  * @param[in] loops The number of static event loops to start (0 to disable the feature)
751  * @param[in] allow_api Whether allocation on a specific loop driven via API should be allowed or not (false by default) */
752 void janus_ice_set_static_event_loops(int loops, gboolean allow_api);
753 /*! \brief Method to return the number of static event loops, if enabled
754  * @returns The number of static event loops, if configured, or 0 if the feature is disabled */
755 int janus_ice_get_static_event_loops(void);
756 /*! \brief Method to check whether loop indication via API is allowed
757  * @returns true if allowed, false otherwise */
758 gboolean janus_ice_is_loop_indication_allowed(void);
759 /*! \brief Method to stop all the static event loops, if enabled
760  * @note This will wait for the related threads to exit, and so may delay the shutdown process */
761 void janus_ice_stop_static_event_loops(void);
762 
763 #endif
764