Imported Upstream version 0.1.17
[platform/upstream/libnice.git] / agent / agent.c
1 /*
2  * This file is part of the Nice GLib ICE library.
3  *
4  * (C) 2006-2010, 2013 Collabora Ltd.
5  *  Contact: Youness Alaoui
6  * (C) 2006-2010 Nokia Corporation. All rights reserved.
7  *  Contact: Kai Vehmanen
8  *
9  * The contents of this file are subject to the Mozilla Public License Version
10  * 1.1 (the "License"); you may not use this file except in compliance with
11  * the License. You may obtain a copy of the License at
12  * http://www.mozilla.org/MPL/
13  *
14  * Software distributed under the License is distributed on an "AS IS" basis,
15  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
16  * for the specific language governing rights and limitations under the
17  * License.
18  *
19  * The Original Code is the Nice GLib ICE library.
20  *
21  * The Initial Developers of the Original Code are Collabora Ltd and Nokia
22  * Corporation. All Rights Reserved.
23  *
24  * Contributors:
25  *   Dafydd Harries, Collabora Ltd.
26  *   Youness Alaoui, Collabora Ltd.
27  *   Kai Vehmanen, Nokia
28  *   Philip Withnall, Collabora Ltd.
29  *
30  * Alternatively, the contents of this file may be used under the terms of the
31  * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
32  * case the provisions of LGPL are applicable instead of those above. If you
33  * wish to allow use of your version of this file only under the terms of the
34  * LGPL and not to allow others to use your version of this file under the
35  * MPL, indicate your decision by deleting the provisions above and replace
36  * them with the notice and other provisions required by the LGPL. If you do
37  * not delete the provisions above, a recipient may use your version of this
38  * file under either the MPL or the LGPL.
39  */
40
41
42 #ifdef HAVE_CONFIG_H
43 # include <config.h>
44 #else
45 #define NICEAPI_EXPORT
46 #endif
47
48 #include <glib.h>
49 #include <gobject/gvaluecollector.h>
50
51 #include <string.h>
52 #include <errno.h>
53
54 #ifndef G_OS_WIN32
55 #include <sys/socket.h>
56 #include <netinet/in.h>
57 #include <arpa/inet.h>
58 #endif
59
60 #include "debug.h"
61
62 #include "socket.h"
63 #include "stun/usages/turn.h"
64 #include "candidate.h"
65 #include "component.h"
66 #include "conncheck.h"
67 #include "discovery.h"
68 #include "agent.h"
69 #include "agent-priv.h"
70 #include "iostream.h"
71
72 #include "stream.h"
73 #include "interfaces.h"
74
75 #include "pseudotcp.h"
76 #include "agent-enum-types.h"
77
78 /* Maximum size of a UDP packet’s payload, as the packet’s length field is 16b
79  * wide. */
80 #define MAX_BUFFER_SIZE ((1 << 16) - 1)  /* 65535 */
81
82 #define DEFAULT_STUN_PORT  3478
83 #define DEFAULT_UPNP_TIMEOUT 200  /* milliseconds */
84 #define DEFAULT_IDLE_TIMEOUT 5000 /* milliseconds */
85
86 #define MAX_TCP_MTU 1400 /* Use 1400 because of VPNs and we assume IEE 802.3 */
87
88
89 static void
90 nice_debug_input_message_composition (const NiceInputMessage *messages,
91     guint n_messages);
92 static const gchar *_cand_type_to_sdp (NiceCandidateType type);
93
94 G_DEFINE_TYPE (NiceAgent, nice_agent, G_TYPE_OBJECT);
95
96 enum
97 {
98   PROP_COMPATIBILITY = 1,
99   PROP_MAIN_CONTEXT,
100   PROP_STUN_SERVER,
101   PROP_STUN_SERVER_PORT,
102   PROP_CONTROLLING_MODE,
103   PROP_FULL_MODE,
104   PROP_STUN_PACING_TIMER,
105   PROP_MAX_CONNECTIVITY_CHECKS,
106   PROP_PROXY_TYPE,
107   PROP_PROXY_IP,
108   PROP_PROXY_PORT,
109   PROP_PROXY_USERNAME,
110   PROP_PROXY_PASSWORD,
111   PROP_UPNP,
112   PROP_UPNP_TIMEOUT,
113   PROP_RELIABLE,
114   PROP_ICE_UDP,
115   PROP_ICE_TCP,
116   PROP_BYTESTREAM_TCP,
117   PROP_KEEPALIVE_CONNCHECK,
118   PROP_FORCE_RELAY,
119   PROP_STUN_MAX_RETRANSMISSIONS,
120   PROP_STUN_INITIAL_TIMEOUT,
121   PROP_STUN_RELIABLE_TIMEOUT,
122   PROP_NOMINATION_MODE,
123   PROP_ICE_TRICKLE,
124   PROP_SUPPORT_RENOMINATION,
125   PROP_IDLE_TIMEOUT,
126 };
127
128
129 enum
130 {
131   SIGNAL_COMPONENT_STATE_CHANGED,
132   SIGNAL_CANDIDATE_GATHERING_DONE,
133   SIGNAL_NEW_SELECTED_PAIR,
134   SIGNAL_NEW_CANDIDATE,
135   SIGNAL_NEW_REMOTE_CANDIDATE,
136   SIGNAL_INITIAL_BINDING_REQUEST_RECEIVED,
137   SIGNAL_RELIABLE_TRANSPORT_WRITABLE,
138   SIGNAL_STREAMS_REMOVED,
139   SIGNAL_NEW_SELECTED_PAIR_FULL,
140   SIGNAL_NEW_CANDIDATE_FULL,
141   SIGNAL_NEW_REMOTE_CANDIDATE_FULL,
142
143   N_SIGNALS,
144 };
145
146 static guint signals[N_SIGNALS];
147
148 static void priv_stop_upnp (NiceAgent *agent);
149
150 static void pseudo_tcp_socket_opened (PseudoTcpSocket *sock, gpointer user_data);
151 static void pseudo_tcp_socket_readable (PseudoTcpSocket *sock, gpointer user_data);
152 static void pseudo_tcp_socket_writable (PseudoTcpSocket *sock, gpointer user_data);
153 static void pseudo_tcp_socket_closed (PseudoTcpSocket *sock, guint32 err,
154     gpointer user_data);
155 static PseudoTcpWriteResult pseudo_tcp_socket_write_packet (PseudoTcpSocket *sock,
156     const gchar *buffer, guint32 len, gpointer user_data);
157 static void adjust_tcp_clock (NiceAgent *agent, NiceStream *stream, NiceComponent *component);
158
159 static void nice_agent_dispose (GObject *object);
160 static void nice_agent_get_property (GObject *object,
161   guint property_id, GValue *value, GParamSpec *pspec);
162 static void nice_agent_set_property (GObject *object,
163   guint property_id, const GValue *value, GParamSpec *pspec);
164
165 void agent_lock (NiceAgent *agent)
166 {
167   g_mutex_lock (&agent->agent_mutex);
168 }
169
170 void agent_unlock (NiceAgent *agent)
171 {
172   g_mutex_unlock (&agent->agent_mutex);
173 }
174
175 static GType _nice_agent_stream_ids_get_type (void);
176
177 G_DEFINE_POINTER_TYPE (_NiceAgentStreamIds, _nice_agent_stream_ids);
178
179 #define NICE_TYPE_AGENT_STREAM_IDS _nice_agent_stream_ids_get_type ()
180
181 typedef struct {
182   guint signal_id;
183   GSignalQuery query;
184   GValue *params;
185 } QueuedSignal;
186
187
188 static void
189 free_queued_signal (QueuedSignal *sig)
190 {
191   guint i;
192
193   g_value_unset (&sig->params[0]);
194
195   for (i = 0; i < sig->query.n_params; i++) {
196     if (G_VALUE_HOLDS(&sig->params[i + 1], NICE_TYPE_AGENT_STREAM_IDS))
197       g_free (g_value_get_pointer (&sig->params[i + 1]));
198     g_value_unset (&sig->params[i + 1]);
199   }
200
201   g_slice_free1 (sizeof(GValue) * (sig->query.n_params + 1), sig->params);
202   g_slice_free (QueuedSignal, sig);
203 }
204
205 void
206 agent_unlock_and_emit (NiceAgent *agent)
207 {
208   GQueue queue = G_QUEUE_INIT;
209   QueuedSignal *sig;
210
211   queue = agent->pending_signals;
212   g_queue_init (&agent->pending_signals);
213
214   agent_unlock (agent);
215
216   while ((sig = g_queue_pop_head (&queue))) {
217     g_signal_emitv (sig->params, sig->signal_id, 0, NULL);
218
219     free_queued_signal (sig);
220   }
221 }
222
223 static void
224 agent_queue_signal (NiceAgent *agent, guint signal_id, ...)
225 {
226   QueuedSignal *sig;
227   guint i;
228   gchar *error = NULL;
229   va_list var_args;
230
231   sig = g_slice_new (QueuedSignal);
232   g_signal_query (signal_id, &sig->query);
233
234   sig->signal_id = signal_id;
235   sig->params = g_slice_alloc0 (sizeof(GValue) * (sig->query.n_params + 1));
236
237   g_value_init (&sig->params[0], G_TYPE_OBJECT);
238   g_value_set_object (&sig->params[0], agent);
239
240   va_start (var_args, signal_id);
241   for (i = 0; i < sig->query.n_params; i++) {
242     G_VALUE_COLLECT_INIT (&sig->params[i + 1], sig->query.param_types[i],
243         var_args, 0, &error);
244     if (error)
245       break;
246   }
247   va_end (var_args);
248
249   if (error) {
250     free_queued_signal (sig);
251     g_critical ("Error collecting values for signal: %s", error);
252     g_free (error);
253     return;
254   }
255
256   g_queue_push_tail (&agent->pending_signals, sig);
257 }
258
259
260 StunUsageIceCompatibility
261 agent_to_ice_compatibility (NiceAgent *agent)
262 {
263   return agent->compatibility == NICE_COMPATIBILITY_GOOGLE ?
264       STUN_USAGE_ICE_COMPATIBILITY_GOOGLE :
265       agent->compatibility == NICE_COMPATIBILITY_MSN ?
266       STUN_USAGE_ICE_COMPATIBILITY_MSN :
267       agent->compatibility == NICE_COMPATIBILITY_WLM2009 ?
268       STUN_USAGE_ICE_COMPATIBILITY_MSICE2 :
269       agent->compatibility == NICE_COMPATIBILITY_OC2007 ?
270       STUN_USAGE_ICE_COMPATIBILITY_MSN :
271       agent->compatibility == NICE_COMPATIBILITY_OC2007R2 ?
272       STUN_USAGE_ICE_COMPATIBILITY_MSICE2 :
273       STUN_USAGE_ICE_COMPATIBILITY_RFC5245;
274 }
275
276
277 StunUsageTurnCompatibility
278 agent_to_turn_compatibility (NiceAgent *agent)
279 {
280   return agent->compatibility == NICE_COMPATIBILITY_GOOGLE ?
281       STUN_USAGE_TURN_COMPATIBILITY_GOOGLE :
282       agent->compatibility == NICE_COMPATIBILITY_MSN ?
283       STUN_USAGE_TURN_COMPATIBILITY_MSN :
284       agent->compatibility == NICE_COMPATIBILITY_WLM2009 ?
285       STUN_USAGE_TURN_COMPATIBILITY_MSN :
286       agent->compatibility == NICE_COMPATIBILITY_OC2007 ?
287       STUN_USAGE_TURN_COMPATIBILITY_OC2007 :
288       agent->compatibility == NICE_COMPATIBILITY_OC2007R2 ?
289       STUN_USAGE_TURN_COMPATIBILITY_OC2007 :
290       STUN_USAGE_TURN_COMPATIBILITY_RFC5766;
291 }
292
293 NiceTurnSocketCompatibility
294 agent_to_turn_socket_compatibility (NiceAgent *agent)
295 {
296   return agent->compatibility == NICE_COMPATIBILITY_GOOGLE ?
297       NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE :
298       agent->compatibility == NICE_COMPATIBILITY_MSN ?
299       NICE_TURN_SOCKET_COMPATIBILITY_MSN :
300       agent->compatibility == NICE_COMPATIBILITY_WLM2009 ?
301       NICE_TURN_SOCKET_COMPATIBILITY_MSN :
302       agent->compatibility == NICE_COMPATIBILITY_OC2007 ?
303       NICE_TURN_SOCKET_COMPATIBILITY_OC2007 :
304       agent->compatibility == NICE_COMPATIBILITY_OC2007R2 ?
305       NICE_TURN_SOCKET_COMPATIBILITY_OC2007 :
306       NICE_TURN_SOCKET_COMPATIBILITY_RFC5766;
307 }
308
309 NiceStream *agent_find_stream (NiceAgent *agent, guint stream_id)
310 {
311   GSList *i;
312
313   for (i = agent->streams; i; i = i->next)
314     {
315       NiceStream *s = i->data;
316
317       if (s->id == stream_id)
318         return s;
319     }
320
321   return NULL;
322 }
323
324
325 gboolean
326 agent_find_component (
327   NiceAgent *agent,
328   guint stream_id,
329   guint component_id,
330   NiceStream **stream,
331   NiceComponent **component)
332 {
333   NiceStream *s;
334   NiceComponent *c;
335
336   s = agent_find_stream (agent, stream_id);
337
338   if (s == NULL)
339     return FALSE;
340
341   c = nice_stream_find_component_by_id (s, component_id);
342
343   if (c == NULL)
344     return FALSE;
345
346   if (stream)
347     *stream = s;
348
349   if (component)
350     *component = c;
351
352   return TRUE;
353 }
354
355 static void
356 nice_agent_class_init (NiceAgentClass *klass)
357 {
358   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
359
360   gobject_class->get_property = nice_agent_get_property;
361   gobject_class->set_property = nice_agent_set_property;
362   gobject_class->dispose = nice_agent_dispose;
363
364   /* install properties */
365   /**
366    * NiceAgent:main-context:
367    *
368    * A GLib main context is needed for all timeouts used by libnice.
369    * This is a property being set by the nice_agent_new() call.
370    */
371   g_object_class_install_property (gobject_class, PROP_MAIN_CONTEXT,
372       g_param_spec_pointer (
373          "main-context",
374          "The GMainContext to use for timeouts",
375          "The GMainContext to use for timeouts",
376          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
377
378   /**
379    * NiceAgent:compatibility:
380    *
381    * The Nice agent can work in various compatibility modes depending on
382    * what the application/peer needs.
383    * <para> See also: #NiceCompatibility</para>
384    */
385   g_object_class_install_property (gobject_class, PROP_COMPATIBILITY,
386       g_param_spec_uint (
387          "compatibility",
388          "ICE specification compatibility",
389          "The compatibility mode for the agent",
390          NICE_COMPATIBILITY_RFC5245, NICE_COMPATIBILITY_LAST,
391          NICE_COMPATIBILITY_RFC5245,
392          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
393
394   g_object_class_install_property (gobject_class, PROP_STUN_SERVER,
395       g_param_spec_string (
396         "stun-server",
397         "STUN server IP address",
398         "The IP address (not the hostname) of the STUN server to use",
399         NULL,
400         G_PARAM_READWRITE));
401
402   g_object_class_install_property (gobject_class, PROP_STUN_SERVER_PORT,
403       g_param_spec_uint (
404         "stun-server-port",
405         "STUN server port",
406         "Port of the STUN server used to gather server-reflexive candidates",
407         1, 65536,
408         1, /* not a construct property, ignored */
409         G_PARAM_READWRITE));
410
411   /**
412    * NiceAgent:controlling-mode:
413    *
414    * Whether the agent has the controlling role. This property should
415    * be modified before gathering candidates, any modification occuring
416    * later will be hold until ICE is restarted.
417    */
418   g_object_class_install_property (gobject_class, PROP_CONTROLLING_MODE,
419       g_param_spec_boolean (
420         "controlling-mode",
421         "ICE controlling mode",
422         "Whether the agent is in controlling mode",
423         FALSE, /* not a construct property, ignored */
424         G_PARAM_READWRITE));
425
426    g_object_class_install_property (gobject_class, PROP_FULL_MODE,
427       g_param_spec_boolean (
428         "full-mode",
429         "ICE full mode",
430         "Whether agent runs in ICE full mode",
431         TRUE, /* use full mode by default */
432         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
433
434   g_object_class_install_property (gobject_class, PROP_STUN_PACING_TIMER,
435       g_param_spec_uint (
436         "stun-pacing-timer",
437         "STUN pacing timer",
438         "Timer 'Ta' (msecs) used in the IETF ICE specification for pacing "
439         "candidate gathering and sending of connectivity checks",
440         1, 0xffffffff,
441         NICE_AGENT_TIMER_TA_DEFAULT,
442         G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
443
444   /* note: according to spec recommendation in sect 5.7.3 (ID-19) */
445   g_object_class_install_property (gobject_class, PROP_MAX_CONNECTIVITY_CHECKS,
446       g_param_spec_uint (
447         "max-connectivity-checks",
448         "Maximum number of connectivity checks",
449         "Upper limit for the total number of connectivity checks performed",
450         0, 0xffffffff,
451         0, /* default set in init */
452         G_PARAM_READWRITE));
453
454   /**
455    * NiceAgent:nomination-mode:
456    *
457    * The nomination mode used in the ICE specification for describing
458    * the selection of valid pairs to be used upstream.
459    * <para> See also: #NiceNominationMode </para>
460    *
461    * Since: 0.1.15
462    */
463   g_object_class_install_property (gobject_class, PROP_NOMINATION_MODE,
464       g_param_spec_enum (
465          "nomination-mode",
466          "ICE nomination mode",
467          "Nomination mode used in the ICE specification for describing "
468          "the selection of valid pairs to be used upstream",
469          NICE_TYPE_NOMINATION_MODE, NICE_NOMINATION_MODE_AGGRESSIVE,
470          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
471
472   /**
473    * NiceAgent:support-renomination:
474    *
475    * Support RENOMINATION STUN attribute proposed here:
476    * https://tools.ietf.org/html/draft-thatcher-ice-renomination-00 As
477    * soon as RENOMINATION attribute is received from remote
478    * candidate's address, corresponding candidates pair gets
479    * selected. This is specific to Google Chrome/libWebRTC.
480    */
481   g_object_class_install_property (gobject_class, PROP_SUPPORT_RENOMINATION,
482       g_param_spec_boolean (
483          "support-renomination",
484          "Support RENOMINATION STUN attribute",
485          "As soon as RENOMINATION attribute is received from remote candidate's address, "
486          "corresponding candidates pair gets selected.",
487          FALSE,
488          G_PARAM_READWRITE));
489
490   /**
491    * NiceAgent:idle-timeout
492    *
493    * A final timeout in msec, launched when the agent becomes idle,
494    * before stopping its activity.
495    *
496    * This timer will delay the decision to set a component as failed.
497    * This delay is added to reduce the chance to see the agent receiving
498    * new stun activity just after the conncheck list has been declared
499    * failed (some valid pairs, no nominated pair, and no in-progress
500    * pairs), reactiviting conncheck activity, and causing a (valid)
501    * state transitions like that: connecting -> failed -> connecting ->
502    * connected -> ready.  Such transitions are not buggy per-se, but may
503    * break the test-suite, that counts precisely the number of time each
504    * state has been set, and doesnt expect these transcient failed
505    * states.
506    *
507    * This timer is also useful when the agent is in controlled mode and
508    * the other controlling peer takes some time to elect its nominated
509    * pair (this may be the case for SfB peers).
510    *
511    * This timer is *NOT* part if the RFC5245, as this situation is not
512    * covered in sect 8.1.2 "Updating States", but deals with a real
513    * use-case, where a controlled agent can not wait forever for the
514    * other peer to make a nomination decision.
515    *
516    * Also note that the value of this timeout will not delay the
517    * emission of 'connected' and 'ready' agent signals, and will not
518    * slow down the behaviour of the agent when the peer agent works
519    * in a timely manner.
520    *
521    * Since: 0.1.17
522    */
523
524   g_object_class_install_property (gobject_class, PROP_IDLE_TIMEOUT,
525       g_param_spec_uint (
526          "idle-timeout",
527          "Timeout before stopping the agent when being idle",
528          "A final timeout in msecs, launched when the agent becomes idle, "
529          "with no in-progress pairs to wait for, before stopping its activity, "
530          "and declaring a component as failed in needed.",
531          50, 60000,
532          DEFAULT_IDLE_TIMEOUT,
533          G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
534
535   /**
536    * NiceAgent:proxy-ip:
537    *
538    * The proxy server IP used to bypass a proxy firewall
539    *
540    * Since: 0.0.4
541    */
542   g_object_class_install_property (gobject_class, PROP_PROXY_IP,
543       g_param_spec_string (
544         "proxy-ip",
545         "Proxy server IP",
546         "The proxy server IP used to bypass a proxy firewall",
547         NULL,
548         G_PARAM_READWRITE));
549
550   /**
551    * NiceAgent:proxy-port:
552    *
553    * The proxy server port used to bypass a proxy firewall
554    *
555    * Since: 0.0.4
556    */
557   g_object_class_install_property (gobject_class, PROP_PROXY_PORT,
558       g_param_spec_uint (
559         "proxy-port",
560         "Proxy server port",
561         "The Proxy server port used to bypass a proxy firewall",
562         1, 65536,
563         1,
564         G_PARAM_READWRITE));
565
566   /**
567    * NiceAgent:proxy-type:
568    *
569    * The type of proxy set in the proxy-ip property
570    *
571    * Since: 0.0.4
572    */
573   g_object_class_install_property (gobject_class, PROP_PROXY_TYPE,
574       g_param_spec_uint (
575          "proxy-type",
576          "Type of proxy to use",
577          "The type of proxy set in the proxy-ip property",
578          NICE_PROXY_TYPE_NONE, NICE_PROXY_TYPE_LAST,
579          NICE_PROXY_TYPE_NONE,
580          G_PARAM_READWRITE));
581
582   /**
583    * NiceAgent:proxy-username:
584    *
585    * The username used to authenticate with the proxy
586    *
587    * Since: 0.0.4
588    */
589   g_object_class_install_property (gobject_class, PROP_PROXY_USERNAME,
590       g_param_spec_string (
591         "proxy-username",
592         "Proxy server username",
593         "The username used to authenticate with the proxy",
594         NULL,
595         G_PARAM_READWRITE));
596
597   /**
598    * NiceAgent:proxy-password:
599    *
600    * The password used to authenticate with the proxy
601    *
602    * Since: 0.0.4
603    */
604   g_object_class_install_property (gobject_class, PROP_PROXY_PASSWORD,
605       g_param_spec_string (
606         "proxy-password",
607         "Proxy server password",
608         "The password used to authenticate with the proxy",
609         NULL,
610         G_PARAM_READWRITE));
611
612   /**
613    * NiceAgent:upnp:
614    *
615    * Whether the agent should use UPnP to open a port in the router and
616    * get the external IP
617    *
618    * Since: 0.0.7
619    */
620    g_object_class_install_property (gobject_class, PROP_UPNP,
621       g_param_spec_boolean (
622         "upnp",
623 #ifdef HAVE_GUPNP
624         "Use UPnP",
625         "Whether the agent should use UPnP to open a port in the router and "
626         "get the external IP",
627 #else
628         "Use UPnP (disabled in build)",
629         "Does nothing because libnice was not built with UPnP support",
630 #endif
631         TRUE, /* enable UPnP by default */
632         G_PARAM_READWRITE| G_PARAM_CONSTRUCT));
633
634   /**
635    * NiceAgent:upnp-timeout:
636    *
637    * The maximum amount of time (in milliseconds) to wait for UPnP discovery to
638    * finish before signaling the #NiceAgent::candidate-gathering-done signal
639    *
640    * Since: 0.0.7
641    */
642   g_object_class_install_property (gobject_class, PROP_UPNP_TIMEOUT,
643       g_param_spec_uint (
644         "upnp-timeout",
645 #ifdef HAVE_GUPNP
646         "Timeout for UPnP discovery",
647         "The maximum amount of time to wait for UPnP discovery to finish before "
648         "signaling the candidate-gathering-done signal",
649 #else
650         "Timeout for UPnP discovery (disabled in build)",
651         "Does nothing because libnice was not built with UPnP support",
652 #endif
653         100, 60000,
654         DEFAULT_UPNP_TIMEOUT,
655         G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
656
657   /**
658    * NiceAgent:reliable:
659    *
660    * Whether the agent is providing a reliable transport of messages (through
661    * ICE-TCP or PseudoTCP over ICE-UDP)
662    *
663    * Since: 0.0.11
664    */
665    g_object_class_install_property (gobject_class, PROP_RELIABLE,
666       g_param_spec_boolean (
667         "reliable",
668         "reliable mode",
669         "Whether the agent provides a reliable transport of messages",
670         FALSE,
671         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
672
673   /**
674    * NiceAgent:ice-udp:
675    *
676    * Whether the agent should use ICE-UDP when gathering candidates.
677    * If the option is disabled, no UDP candidates will be generated. If the
678    * agent is in reliable mode, then pseudotcp will not be used since pseudotcp
679    * works on top of UDP candidates.
680    * <para>
681    * This option should be set before gathering candidates and should not be
682    * modified afterwards.
683    * </para>
684    * The #NiceAgent:ice-udp property can be set at the same time as the
685    * #NiceAgent:ice-tcp property, but both cannot be unset at the same time.
686    * If #NiceAgent:ice-tcp is set to %FALSE, then this property cannot be set
687    * to %FALSE as well.
688    *
689    * Since: 0.1.8
690    */
691    g_object_class_install_property (gobject_class, PROP_ICE_UDP,
692       g_param_spec_boolean (
693         "ice-udp",
694         "Use ICE-UDP",
695         "Use ICE-UDP specification to generate UDP candidates",
696         TRUE, /* use ice-udp by default */
697         G_PARAM_READWRITE));
698
699   /**
700    * NiceAgent:ice-tcp:
701    *
702    * Whether the agent should use ICE-TCP when gathering candidates.
703    * If the option is disabled, no TCP candidates will be generated. If the
704    * agent is in reliable mode, then pseudotcp will need to be used over UDP
705    * candidates.
706    * <para>
707    * This option should be set before gathering candidates and should not be
708    * modified afterwards.
709    * </para>
710    * The #NiceAgent:ice-tcp property can be set at the same time as the
711    * #NiceAgent:ice-udp property, but both cannot be unset at the same time.
712    * If #NiceAgent:ice-udp is set to %FALSE, then this property cannot be set
713    * to %FALSE as well.
714    * <note>
715    <para>
716    ICE-TCP is only supported for %NICE_COMPATIBILITY_RFC5245,
717    %NICE_COMPATIBILITY_OC2007 and %NICE_COMPATIBILITY_OC2007R2 compatibility
718    modes.
719    </para>
720    * </note>
721    *
722    * Since: 0.1.8
723    */
724    g_object_class_install_property (gobject_class, PROP_ICE_TCP,
725       g_param_spec_boolean (
726         "ice-tcp",
727         "Use ICE-TCP",
728         "Use ICE-TCP specification to generate TCP candidates",
729         TRUE, /* use ice-tcp by default */
730         G_PARAM_READWRITE));
731
732   /**
733    * NiceAgent:bytestream-tcp:
734    *
735    * This property defines whether receive/send over a TCP or pseudo-TCP, in
736    * reliable mode, are considered as packetized or as bytestream.
737    * In unreliable mode, every send/recv is considered as packetized, and
738    * this property is ignored and cannot be set.
739    * <para>
740    * In reliable mode, this property will always return %TRUE in the
741    * %NICE_COMPATIBILITY_GOOGLE compatibility mode.
742    * </para>
743    * If the property is %TRUE, the stream is considered in bytestream mode
744    * and data can be read with any receive size. If the property is %FALSE, then
745    * the stream is considred packetized and each receive will return one packet
746    * of the same size as what was sent from the peer. If in packetized mode,
747    * then doing a receive with a size smaller than the packet, will cause the
748    * remaining bytes in the packet to be dropped, breaking the reliability
749    * of the stream.
750    * <para>
751    * This property is currently read-only, and will become read/write once
752    * bytestream mode will be supported.
753    * </para>
754    *
755    * Since: 0.1.8
756    */
757    g_object_class_install_property (gobject_class, PROP_BYTESTREAM_TCP,
758       g_param_spec_boolean (
759         "bytestream-tcp",
760         "Bytestream TCP",
761         "Use bytestream mode for reliable TCP and Pseudo-TCP connections",
762         FALSE,
763         G_PARAM_READABLE));
764
765   /**
766    * NiceAgent:keepalive-conncheck:
767    *
768    * Use binding requests as keepalives instead of binding
769    * indications. This means that the keepalives may time out which
770    * will change the component state to %NICE_COMPONENT_STATE_FAILED.
771    *
772    * Enabing this is a slight violation of RFC 5245 section 10 which
773    * recommends using Binding Indications for keepalives.
774    *
775    * This is always enabled if the compatibility mode is
776    * %NICE_COMPATIBILITY_GOOGLE.
777    *
778    * Since: 0.1.8
779    */
780    g_object_class_install_property (gobject_class, PROP_KEEPALIVE_CONNCHECK,
781       g_param_spec_boolean (
782         "keepalive-conncheck",
783         "Use conncheck as keepalives",
784         "Use binding requests which require a reply as keepalives instead of "
785         "binding indications which don't.",
786         FALSE,
787         G_PARAM_READWRITE));
788
789    /**
790    * NiceAgent:force-relay
791    *
792    * Force all traffic to go through a relay for added privacy, this
793    * allows hiding the local IP address. When this is enabled, so
794    * local candidates are available before relay servers have been set
795    * with nice_agent_set_relay_info().
796    *
797    * Since: 0.1.14
798    */
799    g_object_class_install_property (gobject_class, PROP_FORCE_RELAY,
800       g_param_spec_boolean (
801         "force-relay",
802         "Force Relay",
803         "Force all traffic to go through a relay for added privacy.",
804         FALSE,
805         G_PARAM_READWRITE));
806
807    /**
808    * NiceAgent:stun-max-retransmissions
809    *
810    * The maximum number of retransmissions of the STUN binding requests
811    * used in the gathering stage, to find our local candidates, and used
812    * in the connection check stage, to test the validity of each
813    * constructed pair. This property is described as 'Rc' in the RFC
814    * 5389, with a default value of 7. The timeout of each STUN request
815    * is doubled for each retransmission, so the choice of this value has
816    * a direct impact on the time needed to move from the CONNECTED state
817    * to the READY state, and on the time needed to complete the GATHERING
818    * state.
819    *
820    * Since: 0.1.15
821    */
822
823    g_object_class_install_property (gobject_class, PROP_STUN_MAX_RETRANSMISSIONS,
824       g_param_spec_uint (
825         "stun-max-retransmissions",
826         "STUN Max Retransmissions",
827         "Maximum number of STUN binding requests retransmissions "
828         "described as 'Rc' in the STUN specification.",
829         1, 99,
830         STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS,
831         G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
832
833    /**
834    * NiceAgent:stun-initial-timeout
835    *
836    * The initial timeout (msecs) of the STUN binding requests
837    * used in the gathering stage, to find our local candidates.
838    * This property is described as 'RTO' in the RFC 5389 and RFC 5245.
839    * This timeout is doubled for each retransmission, until
840    * #NiceAgent:stun-max-retransmissions have been done,
841    * with an exception for the last restransmission, where the timeout is
842    * divided by two instead (RFC 5389 indicates that a customisable
843    * multiplier 'Rm' to 'RTO' should be used).
844    *
845    * Since: 0.1.15
846    */
847
848    g_object_class_install_property (gobject_class, PROP_STUN_INITIAL_TIMEOUT,
849       g_param_spec_uint (
850         "stun-initial-timeout",
851         "STUN Initial Timeout",
852         "STUN timeout in msecs of the initial binding requests used in the "
853         "gathering state, described as 'RTO' in the ICE specification.",
854         20, 9999,
855         STUN_TIMER_DEFAULT_TIMEOUT,
856         G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
857
858    /**
859    * NiceAgent:stun-reliable-timeout
860    *
861    * The initial timeout of the STUN binding requests used
862    * for a reliable timer.
863    *
864    * Since: 0.1.15
865    */
866
867    g_object_class_install_property (gobject_class, PROP_STUN_RELIABLE_TIMEOUT,
868       g_param_spec_uint (
869         "stun-reliable-timeout",
870         "STUN Reliable Timeout",
871         "STUN timeout in msecs of the initial binding requests used for "
872         "a reliable timer.",
873         20, 99999,
874         STUN_TIMER_DEFAULT_RELIABLE_TIMEOUT,
875         G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
876
877    /**
878     * NiceAgent:ice-trickle
879     *
880     * Whether to perform Trickle ICE as per draft-ietf-ice-trickle-ice-21.
881     * When %TRUE, the agent will postpone changing a component state to
882     * %NICE_COMPONENT_STATE_FAILED until nice_agent_peer_candidate_gathering_done()
883     * has been called with the ID of the component's stream.
884     *
885     * Since: 0.1.16
886     */
887    g_object_class_install_property (gobject_class, PROP_ICE_TRICKLE,
888       g_param_spec_boolean (
889         "ice-trickle",
890         "Trickle ICE",
891         "Whether to perform Trickle ICE as per draft-ietf-ice-trickle-ice-21.",
892         FALSE,
893         G_PARAM_READWRITE));
894
895   /* install signals */
896
897   /**
898    * NiceAgent::component-state-changed
899    * @agent: The #NiceAgent object
900    * @stream_id: The ID of the stream
901    * @component_id: The ID of the component
902    * @state: The new #NiceComponentState of the component
903    *
904    * This signal is fired whenever a component’s state changes. There are many
905    * valid state transitions.
906    *
907    * ![State transition diagram](states.png)
908    */
909   signals[SIGNAL_COMPONENT_STATE_CHANGED] =
910       g_signal_new (
911           "component-state-changed",
912           G_OBJECT_CLASS_TYPE (klass),
913           G_SIGNAL_RUN_LAST,
914           0,
915           NULL,
916           NULL,
917           NULL,
918           G_TYPE_NONE,
919           3,
920           G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT,
921           G_TYPE_INVALID);
922
923   /**
924    * NiceAgent::candidate-gathering-done:
925    * @agent: The #NiceAgent object
926    * @stream_id: The ID of the stream
927    *
928    * This signal is fired whenever a stream has finished gathering its
929    * candidates after a call to nice_agent_gather_candidates()
930    */
931   signals[SIGNAL_CANDIDATE_GATHERING_DONE] =
932       g_signal_new (
933           "candidate-gathering-done",
934           G_OBJECT_CLASS_TYPE (klass),
935           G_SIGNAL_RUN_LAST,
936           0,
937           NULL,
938           NULL,
939           NULL,
940           G_TYPE_NONE,
941           1,
942           G_TYPE_UINT, G_TYPE_INVALID);
943
944   /**
945    * NiceAgent::new-selected-pair
946    * @agent: The #NiceAgent object
947    * @stream_id: The ID of the stream
948    * @component_id: The ID of the component
949    * @lfoundation: The local foundation of the selected candidate pair
950    * @rfoundation: The remote foundation of the selected candidate pair
951    *
952    * This signal is fired once a candidate pair is selected for data
953    * transfer for a stream's component This is emitted along with
954    * #NiceAgent::new-selected-pair-full which has the whole candidate,
955    * the Foundation of a Candidate is not a unique identifier.
956    *
957    * See also: #NiceAgent::new-selected-pair-full
958    * Deprecated: 0.1.8: Use #NiceAgent::new-selected-pair-full
959    */
960   signals[SIGNAL_NEW_SELECTED_PAIR] =
961       g_signal_new (
962           "new-selected-pair",
963           G_OBJECT_CLASS_TYPE (klass),
964           G_SIGNAL_RUN_LAST,
965           0,
966           NULL,
967           NULL,
968           NULL,
969           G_TYPE_NONE,
970           4,
971           G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING,
972           G_TYPE_INVALID);
973
974   /**
975    * NiceAgent::new-candidate
976    * @agent: The #NiceAgent object
977    * @stream_id: The ID of the stream
978    * @component_id: The ID of the component
979    * @foundation: The foundation of the new candidate
980    *
981    * This signal is fired when the agent discovers a new local candidate.
982    * When this signal is emitted, a matching #NiceAgent::new-candidate-full is
983    * also emitted with the candidate.
984    *
985    * See also: #NiceAgent::candidate-gathering-done,
986    * #NiceAgent::new-candidate-full
987    * Deprecated: 0.1.8: Use #NiceAgent::new-candidate-full
988    */
989   signals[SIGNAL_NEW_CANDIDATE] =
990       g_signal_new (
991           "new-candidate",
992           G_OBJECT_CLASS_TYPE (klass),
993           G_SIGNAL_RUN_LAST,
994           0,
995           NULL,
996           NULL,
997           NULL,
998           G_TYPE_NONE,
999           3,
1000           G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING,
1001           G_TYPE_INVALID);
1002
1003   /**
1004    * NiceAgent::new-remote-candidate
1005    * @agent: The #NiceAgent object
1006    * @stream_id: The ID of the stream
1007    * @component_id: The ID of the component
1008    * @foundation: The foundation of the new candidate
1009    *
1010    * This signal is fired when the agent discovers a new remote
1011    * candidate.  This can happen with peer reflexive candidates.  When
1012    * this signal is emitted, a matching
1013    * #NiceAgent::new-remote-candidate-full is also emitted with the
1014    * candidate.
1015    *
1016    * See also: #NiceAgent::new-remote-candidate-full
1017    * Deprecated: 0.1.8: Use #NiceAgent::new-remote-candidate-full
1018    */
1019   signals[SIGNAL_NEW_REMOTE_CANDIDATE] =
1020       g_signal_new (
1021           "new-remote-candidate",
1022           G_OBJECT_CLASS_TYPE (klass),
1023           G_SIGNAL_RUN_LAST,
1024           0,
1025           NULL,
1026           NULL,
1027           NULL,
1028           G_TYPE_NONE,
1029           3,
1030           G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING,
1031           G_TYPE_INVALID);
1032
1033   /**
1034    * NiceAgent::initial-binding-request-received
1035    * @agent: The #NiceAgent object
1036    * @stream_id: The ID of the stream
1037    *
1038    * This signal is fired when we received our first binding request from
1039    * the peer.
1040    */
1041   signals[SIGNAL_INITIAL_BINDING_REQUEST_RECEIVED] =
1042       g_signal_new (
1043           "initial-binding-request-received",
1044           G_OBJECT_CLASS_TYPE (klass),
1045           G_SIGNAL_RUN_LAST,
1046           0,
1047           NULL,
1048           NULL,
1049           NULL,
1050           G_TYPE_NONE,
1051           1,
1052           G_TYPE_UINT,
1053           G_TYPE_INVALID);
1054
1055   /**
1056    * NiceAgent::reliable-transport-writable
1057    * @agent: The #NiceAgent object
1058    * @stream_id: The ID of the stream
1059    * @component_id: The ID of the component
1060    *
1061    * This signal is fired on the reliable #NiceAgent when the underlying reliable
1062    * transport becomes writable.
1063    * This signal is only emitted when the nice_agent_send() function returns less
1064    * bytes than requested to send (or -1) and once when the connection
1065    * is established.
1066    *
1067    * Since: 0.0.11
1068    */
1069   signals[SIGNAL_RELIABLE_TRANSPORT_WRITABLE] =
1070       g_signal_new (
1071           "reliable-transport-writable",
1072           G_OBJECT_CLASS_TYPE (klass),
1073           G_SIGNAL_RUN_LAST,
1074           0,
1075           NULL,
1076           NULL,
1077           NULL,
1078           G_TYPE_NONE,
1079           2,
1080           G_TYPE_UINT, G_TYPE_UINT,
1081           G_TYPE_INVALID);
1082
1083   /**
1084    * NiceAgent::streams-removed
1085    * @agent: The #NiceAgent object
1086    * @stream_ids: (array zero-terminated=1) (element-type uint): An array of
1087    * unsigned integer stream IDs, ending with a 0 ID
1088    *
1089    * This signal is fired whenever one or more streams are removed from the
1090    * @agent.
1091    *
1092    * Since: 0.1.5
1093    */
1094   signals[SIGNAL_STREAMS_REMOVED] =
1095       g_signal_new (
1096           "streams-removed",
1097           G_OBJECT_CLASS_TYPE (klass),
1098           G_SIGNAL_RUN_LAST,
1099           0,
1100           NULL,
1101           NULL,
1102           g_cclosure_marshal_VOID__POINTER,
1103           G_TYPE_NONE,
1104           1,
1105           NICE_TYPE_AGENT_STREAM_IDS,
1106           G_TYPE_INVALID);
1107
1108
1109   /**
1110    * NiceAgent::new-selected-pair-full
1111    * @agent: The #NiceAgent object
1112    * @stream_id: The ID of the stream
1113    * @component_id: The ID of the component
1114    * @lcandidate: The local #NiceCandidate of the selected candidate pair
1115    * @rcandidate: The remote #NiceCandidate of the selected candidate pair
1116    *
1117    * This signal is fired once a candidate pair is selected for data
1118    * transfer for a stream's component. This is emitted along with
1119    * #NiceAgent::new-selected-pair.
1120    *
1121    * See also: #NiceAgent::new-selected-pair
1122    * Since: 0.1.8
1123    */
1124   signals[SIGNAL_NEW_SELECTED_PAIR_FULL] =
1125       g_signal_new (
1126           "new-selected-pair-full",
1127           G_OBJECT_CLASS_TYPE (klass),
1128           G_SIGNAL_RUN_LAST,
1129           0,
1130           NULL,
1131           NULL,
1132           NULL,
1133           G_TYPE_NONE,
1134           4, G_TYPE_UINT, G_TYPE_UINT, NICE_TYPE_CANDIDATE, NICE_TYPE_CANDIDATE,
1135           G_TYPE_INVALID);
1136
1137   /**
1138    * NiceAgent::new-candidate-full
1139    * @agent: The #NiceAgent object
1140    * @candidate: The new #NiceCandidate
1141    *
1142    * This signal is fired when the agent discovers a new local candidate.
1143    * When this signal is emitted, a matching #NiceAgent::new-candidate is
1144    * also emitted with the candidate's foundation.
1145    *
1146    * See also: #NiceAgent::candidate-gathering-done,
1147    * #NiceAgent::new-candidate
1148    * Since: 0.1.8
1149    */
1150   signals[SIGNAL_NEW_CANDIDATE_FULL] =
1151       g_signal_new (
1152           "new-candidate-full",
1153           G_OBJECT_CLASS_TYPE (klass),
1154           G_SIGNAL_RUN_LAST,
1155           0,
1156           NULL,
1157           NULL,
1158           NULL,
1159           G_TYPE_NONE,
1160           1,
1161           NICE_TYPE_CANDIDATE,
1162           G_TYPE_INVALID);
1163
1164   /**
1165    * NiceAgent::new-remote-candidate-full
1166    * @agent: The #NiceAgent object
1167    * @candidate: The new #NiceCandidate
1168    *
1169    * This signal is fired when the agent discovers a new remote candidate.
1170    * This can happen with peer reflexive candidates.
1171    * When this signal is emitted, a matching #NiceAgent::new-remote-candidate is
1172    * also emitted with the candidate's foundation.
1173    *
1174    * See also: #NiceAgent::new-remote-candidate
1175    * Since: 0.1.8
1176    */
1177   signals[SIGNAL_NEW_REMOTE_CANDIDATE_FULL] =
1178       g_signal_new (
1179           "new-remote-candidate-full",
1180           G_OBJECT_CLASS_TYPE (klass),
1181           G_SIGNAL_RUN_LAST,
1182           0,
1183           NULL,
1184           NULL,
1185           NULL,
1186           G_TYPE_NONE,
1187           1,
1188           NICE_TYPE_CANDIDATE,
1189           G_TYPE_INVALID);
1190
1191   /* Init debug options depending on env variables */
1192   nice_debug_init ();
1193 }
1194
1195 static void priv_generate_tie_breaker (NiceAgent *agent)
1196 {
1197   nice_rng_generate_bytes (agent->rng, 8, (gchar*)&agent->tie_breaker);
1198 }
1199
1200 static void
1201 priv_update_controlling_mode (NiceAgent *agent, gboolean value)
1202 {
1203   gboolean update_controlling_mode;
1204   GSList *i, *j;
1205
1206   agent->saved_controlling_mode = value;
1207   /* It is safe to update the agent controlling mode when all
1208    * components are still in state disconnected. When we leave
1209    * this state, the role must stay under the control of the
1210    * conncheck algorithm exclusively, until the conncheck is
1211    * eventually restarted. See RFC5245, sect 5.2. Determining Role
1212    */
1213   if (agent->controlling_mode != agent->saved_controlling_mode) {
1214     update_controlling_mode = TRUE;
1215     for (i = agent->streams;
1216          i && update_controlling_mode; i = i->next) {
1217       NiceStream *stream = i->data;
1218       for (j = stream->components;
1219            j && update_controlling_mode; j = j->next) {
1220         NiceComponent *component = j->data;
1221         if (component->state > NICE_COMPONENT_STATE_DISCONNECTED)
1222           update_controlling_mode = FALSE;
1223       }
1224     }
1225     if (update_controlling_mode) {
1226       agent->controlling_mode = agent->saved_controlling_mode;
1227       nice_debug ("Agent %p : Property set, changing role to \"%s\".",
1228           agent, agent->controlling_mode ? "controlling" : "controlled");
1229     } else {
1230       nice_debug ("Agent %p : Property set, role switch requested "
1231           "but conncheck already started.", agent);
1232       nice_debug ("Agent %p : Property set, staying with role \"%s\" "
1233           "until restart.", agent,
1234           agent->controlling_mode ? "controlling" : "controlled");
1235     }
1236   } else
1237     nice_debug ("Agent %p : Property set, role is already \"%s\".", agent,
1238         agent->controlling_mode ? "controlling" : "controlled");
1239 }
1240
1241 static void
1242 nice_agent_init (NiceAgent *agent)
1243 {
1244   agent->next_candidate_id = 1;
1245   agent->next_stream_id = 1;
1246
1247   /* set defaults; not construct params, so set here */
1248   agent->stun_server_port = DEFAULT_STUN_PORT;
1249   agent->controlling_mode = TRUE;
1250   agent->saved_controlling_mode = TRUE;
1251   agent->max_conn_checks = NICE_AGENT_MAX_CONNECTIVITY_CHECKS_DEFAULT;
1252   agent->nomination_mode = NICE_NOMINATION_MODE_AGGRESSIVE;
1253   agent->support_renomination = FALSE;
1254   agent->idle_timeout = DEFAULT_IDLE_TIMEOUT;
1255
1256   agent->discovery_list = NULL;
1257   agent->discovery_unsched_items = 0;
1258   agent->discovery_timer_source = NULL;
1259   agent->conncheck_timer_source = NULL;
1260   agent->keepalive_timer_source = NULL;
1261   agent->refresh_list = NULL;
1262   agent->media_after_tick = FALSE;
1263   agent->software_attribute = NULL;
1264
1265   agent->compatibility = NICE_COMPATIBILITY_RFC5245;
1266   agent->reliable = FALSE;
1267   agent->use_ice_udp = TRUE;
1268   agent->use_ice_tcp = TRUE;
1269
1270   agent->rng = nice_rng_new ();
1271   priv_generate_tie_breaker (agent);
1272
1273   g_queue_init (&agent->pending_signals);
1274
1275   g_mutex_init (&agent->agent_mutex);
1276 }
1277
1278
1279 NICEAPI_EXPORT NiceAgent *
1280 nice_agent_new (GMainContext *ctx, NiceCompatibility compat)
1281 {
1282   NiceAgent *agent = g_object_new (NICE_TYPE_AGENT,
1283       "compatibility", compat,
1284       "main-context", ctx,
1285       "reliable", FALSE,
1286       NULL);
1287
1288   return agent;
1289 }
1290
1291
1292 NICEAPI_EXPORT NiceAgent *
1293 nice_agent_new_reliable (GMainContext *ctx, NiceCompatibility compat)
1294 {
1295   NiceAgent *agent = g_object_new (NICE_TYPE_AGENT,
1296       "compatibility", compat,
1297       "main-context", ctx,
1298       "reliable", TRUE,
1299       NULL);
1300
1301   return agent;
1302 }
1303
1304
1305 NICEAPI_EXPORT NiceAgent *
1306 nice_agent_new_full (GMainContext *ctx,
1307   NiceCompatibility compat,
1308   NiceAgentOption flags)
1309 {
1310   NiceAgent *agent = g_object_new (NICE_TYPE_AGENT,
1311       "compatibility", compat,
1312       "main-context", ctx,
1313       "reliable", (flags & NICE_AGENT_OPTION_RELIABLE) ? TRUE : FALSE,
1314       "nomination-mode", (flags & NICE_AGENT_OPTION_REGULAR_NOMINATION) ?
1315       NICE_NOMINATION_MODE_REGULAR : NICE_NOMINATION_MODE_AGGRESSIVE,
1316       "full-mode", (flags & NICE_AGENT_OPTION_LITE_MODE) ? FALSE : TRUE,
1317       "ice-trickle", (flags & NICE_AGENT_OPTION_ICE_TRICKLE) ? TRUE : FALSE,
1318       "support-renomination", (flags & NICE_AGENT_OPTION_SUPPORT_RENOMINATION) ? TRUE : FALSE,
1319       NULL);
1320
1321   return agent;
1322 }
1323
1324
1325 static void
1326 nice_agent_get_property (
1327   GObject *object,
1328   guint property_id,
1329   GValue *value,
1330   GParamSpec *pspec)
1331 {
1332   NiceAgent *agent = NICE_AGENT (object);
1333
1334   agent_lock (agent);
1335
1336   switch (property_id)
1337     {
1338     case PROP_MAIN_CONTEXT:
1339       g_value_set_pointer (value, agent->main_context);
1340       break;
1341
1342     case PROP_COMPATIBILITY:
1343       g_value_set_uint (value, agent->compatibility);
1344       break;
1345
1346     case PROP_STUN_SERVER:
1347       g_value_set_string (value, agent->stun_server_ip);
1348       break;
1349
1350     case PROP_STUN_SERVER_PORT:
1351       g_value_set_uint (value, agent->stun_server_port);
1352       break;
1353
1354     case PROP_CONTROLLING_MODE:
1355       g_value_set_boolean (value, agent->saved_controlling_mode);
1356       break;
1357
1358     case PROP_FULL_MODE:
1359       g_value_set_boolean (value, agent->full_mode);
1360       break;
1361
1362     case PROP_STUN_PACING_TIMER:
1363       g_value_set_uint (value, agent->timer_ta);
1364       break;
1365
1366     case PROP_MAX_CONNECTIVITY_CHECKS:
1367       g_value_set_uint (value, agent->max_conn_checks);
1368       /* XXX: should we prune the list of already existing checks? */
1369       break;
1370
1371     case PROP_NOMINATION_MODE:
1372       g_value_set_enum (value, agent->nomination_mode);
1373       break;
1374
1375     case PROP_SUPPORT_RENOMINATION:
1376       g_value_set_boolean (value, agent->support_renomination);
1377       break;
1378
1379     case PROP_IDLE_TIMEOUT:
1380       g_value_set_uint (value, agent->idle_timeout);
1381       break;
1382
1383     case PROP_PROXY_IP:
1384       g_value_set_string (value, agent->proxy_ip);
1385       break;
1386
1387     case PROP_PROXY_PORT:
1388       g_value_set_uint (value, agent->proxy_port);
1389       break;
1390
1391     case PROP_PROXY_TYPE:
1392       g_value_set_uint (value, agent->proxy_type);
1393       break;
1394
1395     case PROP_PROXY_USERNAME:
1396       g_value_set_string (value, agent->proxy_username);
1397       break;
1398
1399     case PROP_PROXY_PASSWORD:
1400       g_value_set_string (value, agent->proxy_password);
1401       break;
1402
1403     case PROP_UPNP:
1404 #ifdef HAVE_GUPNP
1405       g_value_set_boolean (value, agent->upnp_enabled);
1406 #else
1407       g_value_set_boolean (value, FALSE);
1408 #endif
1409       break;
1410
1411     case PROP_UPNP_TIMEOUT:
1412 #ifdef HAVE_GUPNP
1413       g_value_set_uint (value, agent->upnp_timeout);
1414 #else
1415       g_value_set_uint (value, DEFAULT_UPNP_TIMEOUT);
1416 #endif
1417       break;
1418
1419     case PROP_RELIABLE:
1420       g_value_set_boolean (value, agent->reliable);
1421       break;
1422
1423     case PROP_ICE_UDP:
1424       g_value_set_boolean (value, agent->use_ice_udp);
1425       break;
1426
1427     case PROP_ICE_TCP:
1428       g_value_set_boolean (value, agent->use_ice_tcp);
1429       break;
1430
1431     case PROP_BYTESTREAM_TCP:
1432       if (agent->reliable) {
1433         if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE)
1434           g_value_set_boolean (value, TRUE);
1435         else
1436           g_value_set_boolean (value, FALSE);
1437       } else {
1438         g_value_set_boolean (value, FALSE);
1439       }
1440       break;
1441
1442     case PROP_KEEPALIVE_CONNCHECK:
1443       if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE)
1444         g_value_set_boolean (value, TRUE);
1445       else
1446         g_value_set_boolean (value, agent->keepalive_conncheck);
1447       break;
1448
1449     case PROP_FORCE_RELAY:
1450       g_value_set_boolean (value, agent->force_relay);
1451       break;
1452
1453     case PROP_STUN_MAX_RETRANSMISSIONS:
1454       g_value_set_uint (value, agent->stun_max_retransmissions);
1455       break;
1456
1457     case PROP_STUN_INITIAL_TIMEOUT:
1458       g_value_set_uint (value, agent->stun_initial_timeout);
1459       break;
1460
1461     case PROP_STUN_RELIABLE_TIMEOUT:
1462       g_value_set_uint (value, agent->stun_reliable_timeout);
1463       break;
1464
1465     case PROP_ICE_TRICKLE:
1466       g_value_set_boolean (value, agent->use_ice_trickle);
1467       break;
1468
1469     default:
1470       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1471     }
1472
1473   agent_unlock_and_emit(agent);
1474 }
1475
1476 void
1477 nice_agent_init_stun_agent (NiceAgent *agent, StunAgent *stun_agent)
1478 {
1479   if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE) {
1480     stun_agent_init (stun_agent, STUN_ALL_KNOWN_ATTRIBUTES,
1481         STUN_COMPATIBILITY_RFC3489,
1482         STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS |
1483         STUN_AGENT_USAGE_IGNORE_CREDENTIALS);
1484   } else if (agent->compatibility == NICE_COMPATIBILITY_MSN) {
1485     stun_agent_init (stun_agent, STUN_ALL_KNOWN_ATTRIBUTES,
1486         STUN_COMPATIBILITY_RFC3489,
1487         STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS |
1488         STUN_AGENT_USAGE_FORCE_VALIDATER);
1489   } else if (agent->compatibility == NICE_COMPATIBILITY_WLM2009) {
1490     stun_agent_init (stun_agent, STUN_ALL_KNOWN_ATTRIBUTES,
1491         STUN_COMPATIBILITY_MSICE2,
1492         STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS |
1493         STUN_AGENT_USAGE_USE_FINGERPRINT);
1494   } else if (agent->compatibility == NICE_COMPATIBILITY_OC2007) {
1495     stun_agent_init (stun_agent, STUN_ALL_KNOWN_ATTRIBUTES,
1496         STUN_COMPATIBILITY_RFC3489,
1497         STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS |
1498         STUN_AGENT_USAGE_FORCE_VALIDATER |
1499         STUN_AGENT_USAGE_NO_ALIGNED_ATTRIBUTES);
1500   } else if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2) {
1501     stun_agent_init (stun_agent, STUN_ALL_KNOWN_ATTRIBUTES,
1502         STUN_COMPATIBILITY_MSICE2,
1503         STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS |
1504         STUN_AGENT_USAGE_USE_FINGERPRINT |
1505         STUN_AGENT_USAGE_NO_ALIGNED_ATTRIBUTES);
1506   } else {
1507     stun_agent_init (stun_agent, STUN_ALL_KNOWN_ATTRIBUTES,
1508         STUN_COMPATIBILITY_RFC5389,
1509         STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS |
1510         STUN_AGENT_USAGE_USE_FINGERPRINT);
1511   }
1512   stun_agent_set_software (stun_agent, agent->software_attribute);
1513 }
1514
1515 static void
1516 nice_agent_reset_all_stun_agents (NiceAgent *agent, gboolean only_software)
1517 {
1518   GSList *stream_item, *component_item;
1519
1520   for (stream_item = agent->streams; stream_item;
1521        stream_item = stream_item->next) {
1522     NiceStream *stream = stream_item->data;
1523
1524     for (component_item = stream->components; component_item;
1525          component_item = component_item->next) {
1526       NiceComponent *component = component_item->data;
1527
1528       if (only_software)
1529         stun_agent_set_software (&component->stun_agent,
1530             agent->software_attribute);
1531       else
1532         nice_agent_init_stun_agent(agent, &component->stun_agent);
1533     }
1534   }
1535 }
1536
1537 static void
1538 nice_agent_set_property (
1539   GObject *object,
1540   guint property_id,
1541   const GValue *value,
1542   GParamSpec *pspec)
1543 {
1544   NiceAgent *agent = NICE_AGENT (object);
1545
1546   agent_lock (agent);
1547
1548   switch (property_id)
1549     {
1550     case PROP_MAIN_CONTEXT:
1551       agent->main_context = g_value_get_pointer (value);
1552       if (agent->main_context != NULL)
1553         g_main_context_ref (agent->main_context);
1554       break;
1555
1556     case PROP_COMPATIBILITY:
1557       agent->compatibility = g_value_get_uint (value);
1558       if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE ||
1559           agent->compatibility == NICE_COMPATIBILITY_MSN ||
1560           agent->compatibility == NICE_COMPATIBILITY_WLM2009)
1561         agent->use_ice_tcp = FALSE;
1562
1563       nice_agent_reset_all_stun_agents (agent, FALSE);
1564       break;
1565
1566     case PROP_STUN_SERVER:
1567       g_free (agent->stun_server_ip);
1568       agent->stun_server_ip = g_value_dup_string (value);
1569       break;
1570
1571     case PROP_STUN_SERVER_PORT:
1572       agent->stun_server_port = g_value_get_uint (value);
1573       break;
1574
1575     case PROP_CONTROLLING_MODE:
1576       priv_update_controlling_mode (agent, g_value_get_boolean (value));
1577       break;
1578
1579     case PROP_FULL_MODE:
1580       agent->full_mode = g_value_get_boolean (value);
1581       break;
1582
1583     case PROP_STUN_PACING_TIMER:
1584       agent->timer_ta = g_value_get_uint (value);
1585       break;
1586
1587     case PROP_MAX_CONNECTIVITY_CHECKS:
1588       agent->max_conn_checks = g_value_get_uint (value);
1589       break;
1590
1591     case PROP_NOMINATION_MODE:
1592       agent->nomination_mode = g_value_get_enum (value);
1593       break;
1594
1595     case PROP_SUPPORT_RENOMINATION:
1596       agent->support_renomination = g_value_get_boolean (value);
1597       break;
1598
1599     case PROP_IDLE_TIMEOUT:
1600       agent->idle_timeout = g_value_get_uint (value);
1601       break;
1602
1603     case PROP_PROXY_IP:
1604       g_free (agent->proxy_ip);
1605       agent->proxy_ip = g_value_dup_string (value);
1606       break;
1607
1608     case PROP_PROXY_PORT:
1609       agent->proxy_port = g_value_get_uint (value);
1610       break;
1611
1612     case PROP_PROXY_TYPE:
1613       agent->proxy_type = g_value_get_uint (value);
1614       break;
1615
1616     case PROP_PROXY_USERNAME:
1617       g_free (agent->proxy_username);
1618       agent->proxy_username = g_value_dup_string (value);
1619       break;
1620
1621     case PROP_PROXY_PASSWORD:
1622       g_free (agent->proxy_password);
1623       agent->proxy_password = g_value_dup_string (value);
1624       break;
1625
1626     case PROP_UPNP_TIMEOUT:
1627 #ifdef HAVE_GUPNP
1628       agent->upnp_timeout = g_value_get_uint (value);
1629 #endif
1630       break;
1631
1632     case PROP_UPNP:
1633 #ifdef HAVE_GUPNP
1634       agent->upnp_enabled = g_value_get_boolean (value);
1635 #endif
1636       break;
1637
1638     case PROP_RELIABLE:
1639       agent->reliable = g_value_get_boolean (value);
1640       break;
1641
1642       /* Don't allow ice-udp and ice-tcp to be disabled at the same time */
1643     case PROP_ICE_UDP:
1644       if (agent->use_ice_tcp == TRUE || g_value_get_boolean (value) == TRUE)
1645         agent->use_ice_udp = g_value_get_boolean (value);
1646       break;
1647
1648     case PROP_ICE_TCP:
1649       if ((agent->compatibility == NICE_COMPATIBILITY_RFC5245 ||
1650               agent->compatibility == NICE_COMPATIBILITY_OC2007 ||
1651               agent->compatibility == NICE_COMPATIBILITY_OC2007R2) &&
1652           (agent->use_ice_udp == TRUE || g_value_get_boolean (value) == TRUE))
1653         agent->use_ice_tcp = g_value_get_boolean (value);
1654       break;
1655
1656     case PROP_BYTESTREAM_TCP:
1657       /* TODO: support bytestream mode and set property to writable */
1658       break;
1659
1660     case PROP_KEEPALIVE_CONNCHECK:
1661       agent->keepalive_conncheck = g_value_get_boolean (value);
1662       break;
1663
1664     case PROP_FORCE_RELAY:
1665       agent->force_relay = g_value_get_boolean (value);
1666       break;
1667
1668     case PROP_STUN_MAX_RETRANSMISSIONS:
1669       agent->stun_max_retransmissions = g_value_get_uint (value);
1670       break;
1671
1672     case PROP_STUN_INITIAL_TIMEOUT:
1673       agent->stun_initial_timeout = g_value_get_uint (value);
1674       break;
1675
1676     case PROP_STUN_RELIABLE_TIMEOUT:
1677       agent->stun_reliable_timeout = g_value_get_uint (value);
1678       break;
1679
1680     case PROP_ICE_TRICKLE:
1681       agent->use_ice_trickle = g_value_get_boolean (value);
1682       break;
1683
1684     default:
1685       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1686     }
1687
1688   agent_unlock_and_emit (agent);
1689
1690 }
1691
1692
1693 static void
1694  agent_signal_socket_writable (NiceAgent *agent, NiceComponent *component)
1695 {
1696   g_cancellable_cancel (component->tcp_writable_cancellable);
1697
1698   agent_queue_signal (agent, signals[SIGNAL_RELIABLE_TRANSPORT_WRITABLE],
1699       component->stream_id, component->id);
1700 }
1701
1702 static void
1703 pseudo_tcp_socket_create (NiceAgent *agent, NiceStream *stream, NiceComponent *component)
1704 {
1705   PseudoTcpCallbacks tcp_callbacks = {component,
1706                                       pseudo_tcp_socket_opened,
1707                                       pseudo_tcp_socket_readable,
1708                                       pseudo_tcp_socket_writable,
1709                                       pseudo_tcp_socket_closed,
1710                                       pseudo_tcp_socket_write_packet};
1711   component->tcp = pseudo_tcp_socket_new (0, &tcp_callbacks);
1712   component->tcp_writable_cancellable = g_cancellable_new ();
1713   nice_debug ("Agent %p: Create Pseudo Tcp Socket for component %d",
1714       agent, component->id);
1715 }
1716
1717 static void priv_pseudo_tcp_error (NiceAgent *agent, NiceComponent *component)
1718 {
1719   if (component->tcp_writable_cancellable) {
1720     g_cancellable_cancel (component->tcp_writable_cancellable);
1721     g_clear_object (&component->tcp_writable_cancellable);
1722   }
1723
1724   if (component->tcp) {
1725     agent_signal_component_state_change (agent, component->stream_id,
1726         component->id, NICE_COMPONENT_STATE_FAILED);
1727     nice_component_detach_all_sockets (component);
1728     pseudo_tcp_socket_close (component->tcp, TRUE);
1729   }
1730
1731   if (component->tcp_clock) {
1732     g_source_destroy (component->tcp_clock);
1733     g_source_unref (component->tcp_clock);
1734     component->tcp_clock = NULL;
1735   }
1736 }
1737
1738 static void
1739 pseudo_tcp_socket_opened (PseudoTcpSocket *sock, gpointer user_data)
1740 {
1741   NiceComponent *component = user_data;
1742   NiceAgent *agent;
1743
1744   agent = g_weak_ref_get (&component->agent_ref);
1745   if (agent == NULL)
1746     return;
1747
1748   nice_debug ("Agent %p: s%d:%d pseudo Tcp socket Opened", agent,
1749       component->stream_id, component->id);
1750
1751   agent_signal_socket_writable (agent, component);
1752
1753   g_object_unref (agent);
1754 }
1755
1756 /* Will attempt to queue all @n_messages into the pseudo-TCP transmission
1757  * buffer. This is always used in reliable mode, so essentially treats @messages
1758  * as a massive flat array of buffers.
1759  *
1760  * Returns the number of messages successfully sent on success (which may be
1761  * zero if sending the first buffer of the message would have blocked), or
1762  * a negative number on error. If "allow_partial" is TRUE, then it returns
1763  * the number of bytes sent
1764  */
1765 static gint
1766 pseudo_tcp_socket_send_messages (PseudoTcpSocket *self,
1767     const NiceOutputMessage *messages, guint n_messages, gboolean allow_partial,
1768     GError **error)
1769 {
1770   guint i;
1771   gint bytes_sent = 0;
1772
1773   for (i = 0; i < n_messages; i++) {
1774     const NiceOutputMessage *message = &messages[i];
1775     guint j;
1776
1777     /* If allow_partial is FALSE and there’s not enough space for the
1778      * entire message, bail now before queuing anything. This doesn’t
1779      * gel with the fact this function is only used in reliable mode,
1780      * and there is no concept of a â€˜message’, but is necessary
1781      * because the calling API has no way of returning to the client
1782      * and indicating that a message was partially sent. */
1783     if (!allow_partial &&
1784         output_message_get_size (message) >
1785         pseudo_tcp_socket_get_available_send_space (self)) {
1786       return i;
1787     }
1788
1789     for (j = 0;
1790          (message->n_buffers >= 0 && j < (guint) message->n_buffers) ||
1791          (message->n_buffers < 0 && message->buffers[j].buffer != NULL);
1792          j++) {
1793       const GOutputVector *buffer = &message->buffers[j];
1794       gssize ret;
1795
1796       /* Send on the pseudo-TCP socket. */
1797       ret = pseudo_tcp_socket_send (self, buffer->buffer, buffer->size);
1798
1799       /* In case of -1, the error is either EWOULDBLOCK or ENOTCONN, which both
1800        * need the user to wait for the reliable-transport-writable signal */
1801       if (ret < 0) {
1802         if (pseudo_tcp_socket_get_error (self) == EWOULDBLOCK)
1803           goto out;
1804
1805         if (pseudo_tcp_socket_get_error (self) == ENOTCONN ||
1806             pseudo_tcp_socket_get_error (self) == EPIPE)
1807           g_set_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
1808               "TCP connection is not yet established.");
1809         else
1810           g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
1811             "Error writing data to pseudo-TCP socket.");
1812         return -1;
1813       } else {
1814         bytes_sent += ret;
1815       }
1816     }
1817   }
1818
1819  out:
1820
1821   return allow_partial ? bytes_sent : (gint) i;
1822 }
1823
1824 /* Will fill up @messages from the first free byte onwards (as determined using
1825  * @iter). This is always used in reliable mode, so it essentially treats
1826  * @messages as a massive flat array of buffers.
1827  *
1828  * Updates @iter in place. @iter and @messages are left in invalid states if
1829  * an error is returned.
1830  *
1831  * Returns the number of valid messages in @messages on success (which may be
1832  * zero if no data is pending and the peer has disconnected), or a negative
1833  * number on error (including if the request would have blocked returning no
1834  * messages). */
1835 static gint
1836 pseudo_tcp_socket_recv_messages (PseudoTcpSocket *self,
1837     NiceInputMessage *messages, guint n_messages, NiceInputMessageIter *iter,
1838     GError **error)
1839 {
1840   for (; iter->message < n_messages; iter->message++) {
1841     NiceInputMessage *message = &messages[iter->message];
1842
1843     if (iter->buffer == 0 && iter->offset == 0) {
1844       message->length = 0;
1845     }
1846
1847     for (;
1848          (message->n_buffers >= 0 && iter->buffer < (guint) message->n_buffers) ||
1849          (message->n_buffers < 0 && message->buffers[iter->buffer].buffer != NULL);
1850          iter->buffer++) {
1851       GInputVector *buffer = &message->buffers[iter->buffer];
1852
1853       do {
1854         gssize len;
1855
1856         len = pseudo_tcp_socket_recv (self,
1857             (gchar *) buffer->buffer + iter->offset,
1858             buffer->size - iter->offset);
1859
1860         nice_debug_verbose ("%s: Received %" G_GSSIZE_FORMAT " bytes into "
1861             "buffer %p (offset %" G_GSIZE_FORMAT ", length %" G_GSIZE_FORMAT
1862             ").", G_STRFUNC, len, buffer->buffer, iter->offset, buffer->size);
1863
1864         if (len == 0) {
1865           /* Reached EOS. */
1866           goto done;
1867         } else if (len < 0 &&
1868             pseudo_tcp_socket_get_error (self) == EWOULDBLOCK) {
1869           /* EWOULDBLOCK. If we’ve already received something, return that;
1870            * otherwise, error. */
1871           if (nice_input_message_iter_get_n_valid_messages (iter) > 0) {
1872             goto done;
1873           }
1874           g_set_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
1875               "Error reading data from pseudo-TCP socket: would block.");
1876           return len;
1877         } else if (len < 0 && pseudo_tcp_socket_get_error (self) == ENOTCONN) {
1878           g_set_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
1879               "Error reading data from pseudo-TCP socket: not connected.");
1880           return len;
1881         } else if (len < 0) {
1882           g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
1883               "Error reading data from pseudo-TCP socket.");
1884           return len;
1885         } else {
1886           /* Got some data! */
1887           message->length += len;
1888           iter->offset += len;
1889         }
1890       } while (iter->offset < buffer->size);
1891
1892       iter->offset = 0;
1893     }
1894
1895     iter->buffer = 0;
1896   }
1897
1898 done:
1899   return nice_input_message_iter_get_n_valid_messages (iter);
1900 }
1901
1902 /* This is called with the agent lock held. */
1903 static void
1904 pseudo_tcp_socket_readable (PseudoTcpSocket *sock, gpointer user_data)
1905 {
1906   NiceComponent *component = user_data;
1907   NiceAgent *agent;
1908   gboolean has_io_callback;
1909   NiceStream *stream = NULL;
1910   guint stream_id = component->stream_id;
1911   guint component_id = component->id;
1912
1913   agent = g_weak_ref_get (&component->agent_ref);
1914   if (agent == NULL)
1915     return;
1916
1917   if (!agent_find_component (agent, stream_id, component_id,
1918           &stream, &component)) {
1919     goto out;
1920   }
1921
1922   nice_debug_verbose ("Agent %p: s%d:%d pseudo Tcp socket readable", agent,
1923       stream_id, component->id);
1924
1925   component->tcp_readable = TRUE;
1926
1927   has_io_callback = nice_component_has_io_callback (component);
1928
1929   /* Only dequeue pseudo-TCP data if we can reliably inform the client. The
1930    * agent lock is held here, so has_io_callback can only change during
1931    * nice_component_emit_io_callback(), after which it’s re-queried. This ensures
1932    * no data loss of packets already received and dequeued. */
1933   if (has_io_callback) {
1934     do {
1935       guint8 buf[MAX_BUFFER_SIZE];
1936       gssize len;
1937
1938       /* FIXME: Why copy into a temporary buffer here? Why can’t the I/O
1939        * callbacks be emitted directly from the pseudo-TCP receive buffer? */
1940       len = pseudo_tcp_socket_recv (sock, (gchar *) buf, sizeof(buf));
1941
1942       nice_debug ("%s: I/O callback case: Received %" G_GSSIZE_FORMAT " bytes",
1943           G_STRFUNC, len);
1944
1945       if (len == 0) {
1946         /* Reached EOS. */
1947         component->tcp_readable = FALSE;
1948         pseudo_tcp_socket_close (component->tcp, FALSE);
1949         break;
1950       } else if (len < 0) {
1951         /* Handle errors. */
1952         if (pseudo_tcp_socket_get_error (sock) != EWOULDBLOCK) {
1953           nice_debug ("%s: calling priv_pseudo_tcp_error()", G_STRFUNC);
1954           priv_pseudo_tcp_error (agent, component);
1955         }
1956
1957         if (component->recv_buf_error != NULL) {
1958           GIOErrorEnum error_code;
1959
1960           if (pseudo_tcp_socket_get_error (sock) == ENOTCONN)
1961             error_code = G_IO_ERROR_BROKEN_PIPE;
1962           else if (pseudo_tcp_socket_get_error (sock) == EWOULDBLOCK)
1963             error_code = G_IO_ERROR_WOULD_BLOCK;
1964           else
1965             error_code = G_IO_ERROR_FAILED;
1966
1967           g_set_error (component->recv_buf_error, G_IO_ERROR, error_code,
1968               "Error reading data from pseudo-TCP socket.");
1969         }
1970
1971         break;
1972       }
1973
1974       nice_component_emit_io_callback (agent, component, buf, len);
1975
1976       if (!agent_find_component (agent, stream_id, component_id,
1977               &stream, &component)) {
1978         nice_debug ("Stream or Component disappeared during the callback");
1979         goto out;
1980       }
1981       if (pseudo_tcp_socket_is_closed (component->tcp)) {
1982         nice_debug ("PseudoTCP socket got destroyed in readable callback!");
1983         goto out;
1984       }
1985
1986       has_io_callback = nice_component_has_io_callback (component);
1987     } while (has_io_callback);
1988   } else if (component->recv_messages != NULL) {
1989     gint n_valid_messages;
1990     GError *child_error = NULL;
1991
1992     /* Fill up every buffer in every message until the connection closes or an
1993      * error occurs. Copy the data directly into the client’s receive message
1994      * array without making any callbacks. Update component->recv_messages_iter
1995      * as we go. */
1996     n_valid_messages = pseudo_tcp_socket_recv_messages (sock,
1997         component->recv_messages, component->n_recv_messages,
1998         &component->recv_messages_iter, &child_error);
1999
2000     nice_debug_verbose ("%s: Client buffers case: Received %d valid messages:",
2001         G_STRFUNC, n_valid_messages);
2002     nice_debug_input_message_composition (component->recv_messages,
2003         component->n_recv_messages);
2004
2005     if (n_valid_messages < 0) {
2006       g_propagate_error (component->recv_buf_error, child_error);
2007     } else {
2008       g_clear_error (&child_error);
2009     }
2010
2011     if (n_valid_messages < 0 &&
2012         g_error_matches (child_error, G_IO_ERROR,
2013             G_IO_ERROR_WOULD_BLOCK)) {
2014       component->tcp_readable = FALSE;
2015     } else if (n_valid_messages < 0) {
2016       nice_debug ("%s: calling priv_pseudo_tcp_error()", G_STRFUNC);
2017       priv_pseudo_tcp_error (agent, component);
2018     } else if (n_valid_messages == 0) {
2019       /* Reached EOS. */
2020       component->tcp_readable = FALSE;
2021       pseudo_tcp_socket_close (component->tcp, FALSE);
2022     }
2023   } else {
2024     nice_debug ("%s: no data read", G_STRFUNC);
2025   }
2026
2027   if (stream && component)
2028     adjust_tcp_clock (agent, stream, component);
2029
2030 out:
2031
2032   g_object_unref (agent);
2033 }
2034
2035 static void
2036 pseudo_tcp_socket_writable (PseudoTcpSocket *sock, gpointer user_data)
2037 {
2038   NiceComponent *component = user_data;
2039   NiceAgent *agent;
2040
2041   agent = g_weak_ref_get (&component->agent_ref);
2042   if (agent == NULL)
2043     return;
2044
2045   nice_debug_verbose ("Agent %p: s%d:%d pseudo Tcp socket writable", agent,
2046       component->stream_id, component->id);
2047
2048   agent_signal_socket_writable (agent, component);
2049
2050   g_object_unref (agent);
2051 }
2052
2053 static void
2054 pseudo_tcp_socket_closed (PseudoTcpSocket *sock, guint32 err,
2055     gpointer user_data)
2056 {
2057   NiceComponent *component = user_data;
2058   NiceAgent *agent;
2059
2060   agent = g_weak_ref_get (&component->agent_ref);
2061   if (agent == NULL)
2062     return;
2063
2064   nice_debug ("Agent %p: s%d:%d pseudo Tcp socket closed. "
2065       "Calling priv_pseudo_tcp_error().",  agent, component->stream_id,
2066       component->id);
2067   priv_pseudo_tcp_error (agent, component);
2068
2069   g_object_unref (agent);
2070 }
2071
2072
2073 static PseudoTcpWriteResult
2074 pseudo_tcp_socket_write_packet (PseudoTcpSocket *psocket,
2075     const gchar *buffer, guint32 len, gpointer user_data)
2076 {
2077   NiceComponent *component = user_data;
2078   NiceAgent *agent;
2079
2080   agent = g_weak_ref_get (&component->agent_ref);
2081   if (agent == NULL)
2082     return WR_FAIL;
2083
2084   if (component->selected_pair.local != NULL) {
2085     NiceSocket *sock;
2086     NiceAddress *addr;
2087
2088     sock = component->selected_pair.local->sockptr;
2089     addr = &component->selected_pair.remote->addr;
2090
2091     if (nice_debug_is_enabled ()) {
2092       gchar tmpbuf[INET6_ADDRSTRLEN];
2093       nice_address_to_string (addr, tmpbuf);
2094
2095       nice_debug_verbose (
2096           "Agent %p : s%d:%d: sending %d bytes on socket %p (FD %d) to [%s]:%d",
2097           agent, component->stream_id, component->id, len,
2098           sock->fileno, g_socket_get_fd (sock->fileno), tmpbuf,
2099           nice_address_get_port (addr));
2100     }
2101
2102     /* Send the segment. nice_socket_send() returns 0 on EWOULDBLOCK; in that
2103      * case the segment is not sent on the wire, but we return WR_SUCCESS
2104      * anyway. This effectively drops the segment. The pseudo-TCP state machine
2105      * will eventually pick up this loss and go into recovery mode, reducing
2106      * its transmission rate and, hopefully, the usage of system resources
2107      * which caused the EWOULDBLOCK in the first place. */
2108     if (nice_socket_send (sock, addr, len, buffer) >= 0) {
2109       g_object_unref (agent);
2110       return WR_SUCCESS;
2111     }
2112   } else {
2113     nice_debug ("%s: WARNING: Failed to send pseudo-TCP packet from agent %p "
2114         "as no pair has been selected yet.", G_STRFUNC, agent);
2115   }
2116
2117   g_object_unref (agent);
2118
2119   return WR_FAIL;
2120 }
2121
2122
2123 static gboolean
2124 notify_pseudo_tcp_socket_clock_agent_locked (NiceAgent *agent,
2125     gpointer user_data)
2126 {
2127   NiceComponent *component = user_data;
2128   NiceStream *stream;
2129
2130   stream = agent_find_stream (agent, component->stream_id);
2131   if (!stream)
2132     return G_SOURCE_REMOVE;
2133
2134   pseudo_tcp_socket_notify_clock (component->tcp);
2135   adjust_tcp_clock (agent, stream, component);
2136
2137   return G_SOURCE_CONTINUE;
2138 }
2139
2140 static void
2141 adjust_tcp_clock (NiceAgent *agent, NiceStream *stream, NiceComponent *component)
2142 {
2143   if (!pseudo_tcp_socket_is_closed (component->tcp)) {
2144     guint64 timeout = component->last_clock_timeout;
2145
2146     if (pseudo_tcp_socket_get_next_clock (component->tcp, &timeout)) {
2147       if (timeout != component->last_clock_timeout) {
2148         component->last_clock_timeout = timeout;
2149         if (component->tcp_clock) {
2150           g_source_set_ready_time (component->tcp_clock, timeout * 1000);
2151         }
2152         if (!component->tcp_clock) {
2153           long interval = timeout - (guint32) (g_get_monotonic_time () / 1000);
2154
2155           /* Prevent integer overflows */
2156           if (interval < 0 || interval > G_MAXINT)
2157             interval = G_MAXINT;
2158           agent_timeout_add_with_context (agent, &component->tcp_clock,
2159               "Pseudo-TCP clock", interval,
2160               notify_pseudo_tcp_socket_clock_agent_locked, component);
2161         }
2162       }
2163     } else {
2164       nice_debug ("Agent %p: component %d pseudo-TCP socket should be "
2165           "destroyed. Calling priv_pseudo_tcp_error().",
2166           agent, component->id);
2167       priv_pseudo_tcp_error (agent, component);
2168     }
2169   }
2170 }
2171
2172 void
2173 _tcp_sock_is_writable (NiceSocket *sock, gpointer user_data)
2174 {
2175   NiceComponent *component = user_data;
2176   NiceAgent *agent;
2177
2178   agent = g_weak_ref_get (&component->agent_ref);
2179   if (agent == NULL)
2180     return;
2181
2182   agent_lock (agent);
2183
2184   /* Don't signal writable if the socket that has become writable is not
2185    * the selected pair */
2186   if (component->selected_pair.local == NULL ||
2187       !nice_socket_is_based_on (component->selected_pair.local->sockptr, sock)) {
2188     agent_unlock (agent);
2189     g_object_unref (agent);
2190     return;
2191   }
2192
2193   nice_debug ("Agent %p: s%d:%d Tcp socket writable", agent,
2194       component->stream_id, component->id);
2195   agent_signal_socket_writable (agent, component);
2196
2197   agent_unlock_and_emit (agent);
2198
2199   g_object_unref (agent);
2200 }
2201
2202 static const gchar *
2203 _transport_to_string (NiceCandidateTransport type) {
2204   switch(type) {
2205     case NICE_CANDIDATE_TRANSPORT_UDP:
2206       return "UDP";
2207     case NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE:
2208       return "TCP-ACT";
2209     case NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE:
2210       return "TCP-PASS";
2211     case NICE_CANDIDATE_TRANSPORT_TCP_SO:
2212       return "TCP-SO";
2213     default:
2214       return "???";
2215   }
2216 }
2217
2218 void agent_gathering_done (NiceAgent *agent)
2219 {
2220
2221   GSList *i, *j, *k, *l, *m;
2222
2223   for (i = agent->streams; i; i = i->next) {
2224     NiceStream *stream = i->data;
2225
2226     /* We ignore streams not in gathering state, typically already in
2227      * ready state. Such streams may have couples (local,remote)
2228      * candidates that have not resulted in the creation a new pair
2229      * during a previous conncheck session, and we don't want these new
2230      * pairs to be added now, because it would generate unneeded
2231      * transition changes for a stream unconcerned by this gathering.
2232      */
2233     if (!stream->gathering)
2234       continue;
2235
2236     for (j = stream->components; j; j = j->next) {
2237       NiceComponent *component = j->data;
2238
2239       for (k = component->local_candidates; k;) {
2240         NiceCandidate *local_candidate = k->data;
2241         GSList *next = k->next;
2242
2243         if (agent->force_relay &&
2244             local_candidate->type != NICE_CANDIDATE_TYPE_RELAYED)
2245           goto next_cand;
2246
2247         if (nice_debug_is_enabled ()) {
2248           gchar tmpbuf[INET6_ADDRSTRLEN];
2249           nice_address_to_string (&local_candidate->addr, tmpbuf);
2250           nice_debug ("Agent %p: gathered %s local candidate : [%s]:%u"
2251               " for s%d/c%d. U/P '%s'/'%s'", agent,
2252               _transport_to_string (local_candidate->transport),
2253               tmpbuf, nice_address_get_port (&local_candidate->addr),
2254               local_candidate->stream_id, local_candidate->component_id,
2255               local_candidate->username, local_candidate->password);
2256         }
2257
2258         /* In addition to not contribute to the creation of a pair in the
2259          * conncheck list, according to RFC 5245, sect.  5.7.3 "Pruning the
2260          * Pairs", it can be guessed from SfB behavior, that server
2261          * reflexive pairs are expected to be also removed from the
2262          * candidates list, when pairs are formed, so they have no way to
2263          * become part of a selected pair with such type.
2264          *
2265          * It can be observed that, each time a valid pair is discovered and
2266          * nominated with a local candidate of type srv-rflx, is makes SfB
2267          * fails with a 500 Internal Error.
2268          *
2269          * On the contrary, when a local srv-rflx candidate is gathered,
2270          * normally announced in the sdp, but removed from the candidate
2271          * list, in that case, when the *same* candidate is discovered again
2272          * later during the conncheck, with peer-rflx type this time, then
2273          * it just works.
2274          */
2275
2276         if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2 &&
2277             local_candidate->type == NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE) {
2278           nice_debug ("Agent %p: removing this previous srv-rflx candidate "
2279               "for OC2007R2 compatibility", agent);
2280           component->local_candidates =
2281               g_slist_remove (component->local_candidates, local_candidate);
2282           agent_remove_local_candidate (agent, local_candidate);
2283           nice_candidate_free (local_candidate);
2284           goto next_cand;
2285         }
2286
2287         for (l = component->remote_candidates; l; l = l->next) {
2288           NiceCandidate *remote_candidate = l->data;
2289
2290           for (m = stream->conncheck_list; m; m = m->next) {
2291             CandidateCheckPair *p = m->data;
2292
2293             if (p->local == local_candidate && p->remote == remote_candidate)
2294               break;
2295           }
2296           if (m == NULL) {
2297             conn_check_add_for_candidate_pair (agent, stream->id, component,
2298                 local_candidate, remote_candidate);
2299           }
2300         }
2301 next_cand:
2302         k = next;
2303       }
2304     }
2305   }
2306
2307 #ifdef HAVE_GUPNP
2308   if (agent->discovery_timer_source == NULL &&
2309       agent->upnp_timer_source == NULL) {
2310     agent_signal_gathering_done (agent);
2311   }
2312 #else
2313   if (agent->discovery_timer_source == NULL)
2314     agent_signal_gathering_done (agent);
2315 #endif
2316 }
2317
2318 void agent_signal_gathering_done (NiceAgent *agent)
2319 {
2320   GSList *i;
2321
2322   for (i = agent->streams; i; i = i->next) {
2323     NiceStream *stream = i->data;
2324     if (stream->gathering) {
2325       stream->gathering = FALSE;
2326       agent_queue_signal (agent, signals[SIGNAL_CANDIDATE_GATHERING_DONE],
2327           stream->id);
2328     }
2329   }
2330 }
2331
2332 void
2333 agent_signal_initial_binding_request_received (NiceAgent *agent,
2334     NiceStream *stream)
2335 {
2336   if (stream->initial_binding_request_received != TRUE) {
2337     stream->initial_binding_request_received = TRUE;
2338     agent_queue_signal (agent, signals[SIGNAL_INITIAL_BINDING_REQUEST_RECEIVED],
2339         stream->id);
2340   }
2341 }
2342
2343 /* If the Component now has a selected_pair, and has pending TCP packets which
2344  * it couldn’t receive before due to not being able to send out ACKs (or
2345  * SYNACKs, for the initial SYN packet), handle them now.
2346  *
2347  * Must be called with the agent lock held. */
2348 static void
2349 process_queued_tcp_packets (NiceAgent *agent, NiceStream *stream,
2350     NiceComponent *component)
2351 {
2352   GOutputVector *vec;
2353   guint stream_id = stream->id;
2354   guint component_id = component->id;
2355
2356   g_assert (agent->reliable);
2357
2358   if (component->selected_pair.local == NULL ||
2359       pseudo_tcp_socket_is_closed (component->tcp) ||
2360       nice_socket_is_reliable (component->selected_pair.local->sockptr)) {
2361     return;
2362   }
2363
2364   nice_debug_verbose ("%s: Sending outstanding packets for agent %p.", G_STRFUNC,
2365       agent);
2366
2367   while ((vec = g_queue_peek_head (&component->queued_tcp_packets)) != NULL) {
2368     gboolean retval;
2369
2370     nice_debug ("%s: Sending %" G_GSIZE_FORMAT " bytes.", G_STRFUNC, vec->size);
2371     retval =
2372         pseudo_tcp_socket_notify_packet (component->tcp, vec->buffer,
2373             vec->size);
2374
2375     if (!agent_find_component (agent, stream_id, component_id,
2376             &stream, &component)) {
2377       nice_debug ("Stream or Component disappeared during "
2378           "pseudo_tcp_socket_notify_packet()");
2379       return;
2380     }
2381     if (pseudo_tcp_socket_is_closed (component->tcp)) {
2382       nice_debug ("PseudoTCP socket got destroyed in"
2383           " pseudo_tcp_socket_notify_packet()!");
2384       return;
2385     }
2386
2387     adjust_tcp_clock (agent, stream, component);
2388
2389     if (!retval) {
2390       /* Failed to send; try again later. */
2391       break;
2392     }
2393
2394     g_queue_pop_head (&component->queued_tcp_packets);
2395     g_free ((gpointer) vec->buffer);
2396     g_slice_free (GOutputVector, vec);
2397   }
2398 }
2399
2400 void agent_signal_new_selected_pair (NiceAgent *agent, guint stream_id,
2401     guint component_id, NiceCandidate *lcandidate, NiceCandidate *rcandidate)
2402 {
2403   NiceComponent *component;
2404   NiceStream *stream;
2405
2406   if (!agent_find_component (agent, stream_id, component_id,
2407           &stream, &component))
2408     return;
2409
2410   if (((NiceSocket *)lcandidate->sockptr)->type == NICE_SOCKET_TYPE_UDP_TURN) {
2411     nice_udp_turn_socket_set_peer (lcandidate->sockptr, &rcandidate->addr);
2412   }
2413
2414   if(agent->reliable && !nice_socket_is_reliable (lcandidate->sockptr)) {
2415     if (!component->tcp)
2416       pseudo_tcp_socket_create (agent, stream, component);
2417     process_queued_tcp_packets (agent, stream, component);
2418
2419     pseudo_tcp_socket_connect (component->tcp);
2420     pseudo_tcp_socket_notify_mtu (component->tcp, MAX_TCP_MTU);
2421     adjust_tcp_clock (agent, stream, component);
2422   }
2423
2424   if (nice_debug_is_enabled ()) {
2425     gchar ip[100];
2426     guint port;
2427
2428     port = nice_address_get_port (&lcandidate->addr);
2429     nice_address_to_string (&lcandidate->addr, ip);
2430
2431     nice_debug ("Agent %p: Local selected pair: %d:%d %s %s %s:%d %s",
2432         agent, stream_id, component_id, lcandidate->foundation,
2433         lcandidate->transport == NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE ?
2434         "TCP-ACT" :
2435         lcandidate->transport == NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE ?
2436         "TCP-PASS" :
2437         lcandidate->transport == NICE_CANDIDATE_TRANSPORT_UDP ? "UDP" : "???",
2438         ip, port, lcandidate->type == NICE_CANDIDATE_TYPE_HOST ? "HOST" :
2439         lcandidate->type == NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE ?
2440         "SRV-RFLX" :
2441         lcandidate->type == NICE_CANDIDATE_TYPE_RELAYED ?
2442         "RELAYED" :
2443         lcandidate->type == NICE_CANDIDATE_TYPE_PEER_REFLEXIVE ?
2444         "PEER-RFLX" : "???");
2445
2446     port = nice_address_get_port (&rcandidate->addr);
2447     nice_address_to_string (&rcandidate->addr, ip);
2448
2449     nice_debug ("Agent %p: Remote selected pair: %d:%d %s %s %s:%d %s",
2450         agent, stream_id, component_id, rcandidate->foundation,
2451         rcandidate->transport == NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE ?
2452         "TCP-ACT" :
2453         rcandidate->transport == NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE ?
2454         "TCP-PASS" :
2455         rcandidate->transport == NICE_CANDIDATE_TRANSPORT_UDP ? "UDP" : "???",
2456         ip, port, rcandidate->type == NICE_CANDIDATE_TYPE_HOST ? "HOST" :
2457         rcandidate->type == NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE ?
2458         "SRV-RFLX" :
2459         rcandidate->type == NICE_CANDIDATE_TYPE_RELAYED ?
2460         "RELAYED" :
2461         rcandidate->type == NICE_CANDIDATE_TYPE_PEER_REFLEXIVE ?
2462         "PEER-RFLX" : "???");
2463   }
2464
2465   agent_queue_signal (agent, signals[SIGNAL_NEW_SELECTED_PAIR_FULL],
2466       stream_id, component_id, lcandidate, rcandidate);
2467   agent_queue_signal (agent, signals[SIGNAL_NEW_SELECTED_PAIR],
2468       stream_id, component_id, lcandidate->foundation, rcandidate->foundation);
2469
2470   if(agent->reliable && nice_socket_is_reliable (lcandidate->sockptr)) {
2471     agent_signal_socket_writable (agent, component);
2472   }
2473 }
2474
2475 void agent_signal_new_candidate (NiceAgent *agent, NiceCandidate *candidate)
2476 {
2477   agent_queue_signal (agent, signals[SIGNAL_NEW_CANDIDATE_FULL],
2478       candidate);
2479   agent_queue_signal (agent, signals[SIGNAL_NEW_CANDIDATE],
2480       candidate->stream_id, candidate->component_id, candidate->foundation);
2481 }
2482
2483 void agent_signal_new_remote_candidate (NiceAgent *agent, NiceCandidate *candidate)
2484 {
2485   agent_queue_signal (agent, signals[SIGNAL_NEW_REMOTE_CANDIDATE_FULL],
2486       candidate);
2487   agent_queue_signal (agent, signals[SIGNAL_NEW_REMOTE_CANDIDATE],
2488       candidate->stream_id, candidate->component_id, candidate->foundation);
2489 }
2490
2491 NICEAPI_EXPORT const gchar *
2492 nice_component_state_to_string (NiceComponentState state)
2493 {
2494   switch (state)
2495     {
2496       case NICE_COMPONENT_STATE_DISCONNECTED:
2497         return "disconnected";
2498       case NICE_COMPONENT_STATE_GATHERING:
2499         return "gathering";
2500       case NICE_COMPONENT_STATE_CONNECTING:
2501         return "connecting";
2502       case NICE_COMPONENT_STATE_CONNECTED:
2503         return "connected";
2504       case NICE_COMPONENT_STATE_READY:
2505         return "ready";
2506       case NICE_COMPONENT_STATE_FAILED:
2507         return "failed";
2508       case NICE_COMPONENT_STATE_LAST:
2509       default:
2510         return "invalid";
2511     }
2512 }
2513
2514 void agent_signal_component_state_change (NiceAgent *agent, guint stream_id, guint component_id, NiceComponentState new_state)
2515 {
2516   NiceComponentState old_state;
2517   NiceComponent *component;
2518   NiceStream *stream;
2519
2520   g_return_if_fail (new_state < NICE_COMPONENT_STATE_LAST);
2521
2522   if (!agent_find_component (agent, stream_id, component_id,
2523           &stream, &component))
2524     return;
2525
2526   /* Validate the state change. */
2527   old_state = component->state;
2528
2529   if (new_state == old_state) {
2530     return;
2531   }
2532
2533   nice_debug ("Agent %p : stream %u component %u STATE-CHANGE %s -> %s.", agent,
2534       stream_id, component_id, nice_component_state_to_string (old_state),
2535       nice_component_state_to_string (new_state));
2536
2537   /* Check whether it’s a valid state transition. */
2538 #define TRANSITION(OLD, NEW) \
2539   (old_state == NICE_COMPONENT_STATE_##OLD && \
2540    new_state == NICE_COMPONENT_STATE_##NEW)
2541
2542   g_assert (/* Can (almost) always transition to FAILED (including
2543              * DISCONNECTED â†’ FAILED which happens if one component fails
2544              * before another leaves DISCONNECTED): */
2545             TRANSITION (DISCONNECTED, FAILED) ||
2546             TRANSITION (GATHERING, FAILED) ||
2547             TRANSITION (CONNECTING, FAILED) ||
2548             TRANSITION (CONNECTED, FAILED) ||
2549             TRANSITION (READY, FAILED) ||
2550             /* Standard progression towards a ready connection: */
2551             TRANSITION (DISCONNECTED, GATHERING) ||
2552             TRANSITION (GATHERING, CONNECTING) ||
2553             TRANSITION (CONNECTING, CONNECTED) ||
2554             TRANSITION (CONNECTED, READY) ||
2555             /* priv_conn_check_add_for_candidate_pair_matched(): */
2556             TRANSITION (READY, CONNECTED) ||
2557             /* If set_remote_candidates() is called with new candidates after
2558              * reaching FAILED: */
2559             TRANSITION (FAILED, CONNECTING) ||
2560             /* if new relay servers are added to a failed connection */
2561             TRANSITION (FAILED, GATHERING) ||
2562             /* Possible by calling set_remote_candidates() without calling
2563              * nice_agent_gather_candidates(): */
2564             TRANSITION (DISCONNECTED, CONNECTING));
2565
2566 #undef TRANSITION
2567
2568   component->state = new_state;
2569
2570   if (agent->reliable)
2571     process_queued_tcp_packets (agent, stream, component);
2572
2573   agent_queue_signal (agent, signals[SIGNAL_COMPONENT_STATE_CHANGED],
2574       stream_id, component_id, new_state);
2575 }
2576
2577 guint64
2578 agent_candidate_pair_priority (NiceAgent *agent, NiceCandidate *local, NiceCandidate *remote)
2579 {
2580   if (agent->controlling_mode)
2581     return nice_candidate_pair_priority (local->priority, remote->priority);
2582   else
2583     return nice_candidate_pair_priority (remote->priority, local->priority);
2584 }
2585
2586 static void
2587 priv_add_new_candidate_discovery_stun (NiceAgent *agent,
2588     NiceSocket *nicesock, NiceAddress server,
2589     NiceStream *stream, guint component_id)
2590 {
2591   CandidateDiscovery *cdisco;
2592
2593   /* note: no need to check for redundant candidates, as this is
2594    *       done later on in the process */
2595
2596   cdisco = g_slice_new0 (CandidateDiscovery);
2597
2598   cdisco->type = NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE;
2599   cdisco->nicesock = nicesock;
2600   cdisco->server = server;
2601   cdisco->stream_id = stream->id;
2602   cdisco->component_id = component_id;
2603   stun_agent_init (&cdisco->stun_agent, STUN_ALL_KNOWN_ATTRIBUTES,
2604       STUN_COMPATIBILITY_RFC3489,
2605       (agent->compatibility == NICE_COMPATIBILITY_OC2007 ||
2606        agent->compatibility == NICE_COMPATIBILITY_OC2007R2) ?
2607         STUN_AGENT_USAGE_NO_ALIGNED_ATTRIBUTES : 0);
2608
2609   nice_debug ("Agent %p : Adding new srv-rflx candidate discovery %p",
2610       agent, cdisco);
2611
2612   agent->discovery_list = g_slist_append (agent->discovery_list, cdisco);
2613   ++agent->discovery_unsched_items;
2614 }
2615
2616 NiceSocket *
2617 agent_create_tcp_turn_socket (NiceAgent *agent, NiceStream *stream,
2618     NiceComponent *component, NiceSocket *nicesock,
2619     NiceAddress *server, NiceRelayType type, gboolean reliable_tcp)
2620 {
2621   NiceAddress proxy_server;
2622   NiceAddress local_address = nicesock->addr;
2623
2624   nice_address_set_port (&local_address, 0);
2625   nicesock = NULL;
2626
2627   /* TODO: add support for turn-tcp RFC 6062 */
2628   if (agent->proxy_type != NICE_PROXY_TYPE_NONE &&
2629       agent->proxy_ip != NULL &&
2630       nice_address_set_from_string (&proxy_server, agent->proxy_ip)) {
2631     nice_address_set_port (&proxy_server, agent->proxy_port);
2632     nicesock = nice_tcp_bsd_socket_new (agent->main_context, &local_address,
2633         &proxy_server, reliable_tcp);
2634
2635     if (nicesock) {
2636       _priv_set_socket_tos (agent, nicesock, stream->tos);
2637       if (agent->proxy_type == NICE_PROXY_TYPE_SOCKS5) {
2638         nicesock = nice_socks5_socket_new (nicesock, server,
2639             agent->proxy_username, agent->proxy_password);
2640       } else if (agent->proxy_type == NICE_PROXY_TYPE_HTTP){
2641         nicesock = nice_http_socket_new (nicesock, server,
2642             agent->proxy_username, agent->proxy_password);
2643       } else {
2644         nice_socket_free (nicesock);
2645         nicesock = NULL;
2646       }
2647     }
2648   }
2649
2650   if (nicesock == NULL) {
2651     nicesock = nice_tcp_bsd_socket_new (agent->main_context, &local_address,
2652         server, reliable_tcp);
2653
2654     if (nicesock)
2655       _priv_set_socket_tos (agent, nicesock, stream->tos);
2656   }
2657
2658   /* The TURN server may be invalid or not listening */
2659   if (nicesock == NULL)
2660     return NULL;
2661
2662   nice_socket_set_writable_callback (nicesock, _tcp_sock_is_writable,
2663       component);
2664
2665   if (type ==  NICE_RELAY_TYPE_TURN_TLS &&
2666       agent->compatibility == NICE_COMPATIBILITY_GOOGLE) {
2667     nicesock = nice_pseudossl_socket_new (nicesock,
2668         NICE_PSEUDOSSL_SOCKET_COMPATIBILITY_GOOGLE);
2669   } else if (type == NICE_RELAY_TYPE_TURN_TLS &&
2670       (agent->compatibility == NICE_COMPATIBILITY_OC2007 ||
2671           agent->compatibility == NICE_COMPATIBILITY_OC2007R2)) {
2672     nicesock = nice_pseudossl_socket_new (nicesock,
2673         NICE_PSEUDOSSL_SOCKET_COMPATIBILITY_MSOC);
2674   }
2675   return nice_udp_turn_over_tcp_socket_new (nicesock,
2676       agent_to_turn_socket_compatibility (agent));
2677 }
2678
2679 static void
2680 priv_add_new_candidate_discovery_turn (NiceAgent *agent,
2681     NiceSocket *nicesock, TurnServer *turn,
2682     NiceStream *stream, guint component_id, gboolean turn_tcp)
2683 {
2684   CandidateDiscovery *cdisco;
2685   NiceComponent *component = nice_stream_find_component_by_id (stream, component_id);
2686
2687   /* note: no need to check for redundant candidates, as this is
2688    *       done later on in the process */
2689
2690   cdisco = g_slice_new0 (CandidateDiscovery);
2691   cdisco->type = NICE_CANDIDATE_TYPE_RELAYED;
2692
2693   if (turn->type == NICE_RELAY_TYPE_TURN_UDP) {
2694     if (agent->use_ice_udp == FALSE || turn_tcp == TRUE) {
2695       g_slice_free (CandidateDiscovery, cdisco);
2696       return;
2697     }
2698     if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE) {
2699       NiceAddress addr = nicesock->addr;
2700       NiceSocket *new_socket;
2701       nice_address_set_port (&addr, 0);
2702
2703       new_socket = nice_udp_bsd_socket_new (&addr);
2704       if (new_socket) {
2705         _priv_set_socket_tos (agent, new_socket, stream->tos);
2706         nice_component_attach_socket (component, new_socket);
2707         nicesock = new_socket;
2708       }
2709     }
2710     cdisco->nicesock = nicesock;
2711   } else {
2712     gboolean reliable_tcp = FALSE;
2713
2714     /* MS-TURN will allocate a transport with the same protocol it received
2715      * the allocate request. So if we are connecting in TCP, then the candidate
2716      * will be TCP-ACT/TCP-PASS which means it will be reliable all the way
2717      * to the peer.
2718      * [MS-TURN] : The transport address has the same transport protocol
2719      * over which the Allocate request was received; a request that is
2720      * received over TCP returns a TCP allocated transport address.
2721      */
2722     /* TURN-TCP is currently unsupport unless it's OC2007 compatibliity */
2723     /* TODO: Add support for TURN-TCP */
2724     if (turn_tcp &&
2725         (agent->compatibility == NICE_COMPATIBILITY_OC2007 ||
2726          agent->compatibility == NICE_COMPATIBILITY_OC2007R2))
2727       reliable_tcp = TRUE;
2728
2729     /* Ignore tcp candidates if we disabled ice-tcp */
2730     if ((agent->use_ice_udp == FALSE && reliable_tcp == FALSE) ||
2731         (agent->use_ice_tcp == FALSE && reliable_tcp == TRUE)) {
2732       g_slice_free (CandidateDiscovery, cdisco);
2733       return;
2734     }
2735
2736     if (turn_tcp == FALSE) {
2737       g_slice_free (CandidateDiscovery, cdisco);
2738       return;
2739     }
2740
2741     cdisco->nicesock = agent_create_tcp_turn_socket (agent, stream,
2742         component, nicesock, &turn->server, turn->type, reliable_tcp);
2743
2744     nice_component_attach_socket (component, cdisco->nicesock);
2745   }
2746
2747   cdisco->turn = turn_server_ref (turn);
2748   cdisco->server = turn->server;
2749
2750   cdisco->stream_id = stream->id;
2751   cdisco->component_id = component_id;
2752
2753   if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE) {
2754     stun_agent_init (&cdisco->stun_agent, STUN_ALL_KNOWN_ATTRIBUTES,
2755         STUN_COMPATIBILITY_RFC3489,
2756         STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS |
2757         STUN_AGENT_USAGE_IGNORE_CREDENTIALS);
2758   } else if (agent->compatibility == NICE_COMPATIBILITY_MSN ||
2759       agent->compatibility == NICE_COMPATIBILITY_WLM2009) {
2760     stun_agent_init (&cdisco->stun_agent, STUN_ALL_KNOWN_ATTRIBUTES,
2761         STUN_COMPATIBILITY_RFC3489,
2762         STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS);
2763   } else if (agent->compatibility == NICE_COMPATIBILITY_OC2007 ||
2764       agent->compatibility == NICE_COMPATIBILITY_OC2007R2) {
2765     stun_agent_init (&cdisco->stun_agent, STUN_MSOC_KNOWN_ATTRIBUTES,
2766         STUN_COMPATIBILITY_OC2007,
2767         STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS |
2768         STUN_AGENT_USAGE_NO_ALIGNED_ATTRIBUTES);
2769   } else {
2770     stun_agent_init (&cdisco->stun_agent, STUN_ALL_KNOWN_ATTRIBUTES,
2771         STUN_COMPATIBILITY_RFC5389,
2772         STUN_AGENT_USAGE_ADD_SOFTWARE |
2773         STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS);
2774   }
2775   stun_agent_set_software (&cdisco->stun_agent, agent->software_attribute);
2776
2777   nice_debug ("Agent %p : Adding new relay-rflx candidate discovery %p",
2778       agent, cdisco);
2779   agent->discovery_list = g_slist_append (agent->discovery_list, cdisco);
2780   ++agent->discovery_unsched_items;
2781 }
2782
2783 NICEAPI_EXPORT guint
2784 nice_agent_add_stream (
2785   NiceAgent *agent,
2786   guint n_components)
2787 {
2788   NiceStream *stream;
2789   guint ret = 0;
2790   guint i;
2791
2792   g_return_val_if_fail (NICE_IS_AGENT (agent), 0);
2793   g_return_val_if_fail (n_components >= 1, 0);
2794
2795   agent_lock (agent);
2796   stream = nice_stream_new (agent->next_stream_id++, n_components, agent);
2797
2798   agent->streams = g_slist_append (agent->streams, stream);
2799   nice_debug ("Agent %p : allocating stream id %u (%p)", agent, stream->id, stream);
2800   if (agent->reliable) {
2801     nice_debug ("Agent %p : reliable stream", agent);
2802     for (i = 0; i < n_components; i++) {
2803       NiceComponent *component = nice_stream_find_component_by_id (stream, i + 1);
2804       if (component) {
2805         pseudo_tcp_socket_create (agent, stream, component);
2806       } else {
2807         nice_debug ("Agent %p: couldn't find component %d", agent, i+1);
2808       }
2809     }
2810   }
2811
2812   nice_stream_initialize_credentials (stream, agent->rng);
2813
2814   ret = stream->id;
2815
2816   agent_unlock_and_emit (agent);
2817   return ret;
2818 }
2819
2820
2821 NICEAPI_EXPORT gboolean
2822 nice_agent_set_relay_info(NiceAgent *agent,
2823     guint stream_id, guint component_id,
2824     const gchar *server_ip, guint server_port,
2825     const gchar *username, const gchar *password,
2826     NiceRelayType type)
2827 {
2828
2829   NiceComponent *component = NULL;
2830   NiceStream *stream = NULL;
2831   gboolean ret = TRUE;
2832   TurnServer *turn;
2833   guint length;
2834
2835   g_return_val_if_fail (NICE_IS_AGENT (agent), FALSE);
2836   g_return_val_if_fail (stream_id >= 1, FALSE);
2837   g_return_val_if_fail (component_id >= 1, FALSE);
2838   g_return_val_if_fail (server_ip, FALSE);
2839   g_return_val_if_fail (server_port, FALSE);
2840   g_return_val_if_fail (username, FALSE);
2841   g_return_val_if_fail (password, FALSE);
2842   g_return_val_if_fail (type <= NICE_RELAY_TYPE_TURN_TLS, FALSE);
2843
2844   agent_lock (agent);
2845
2846   if (!agent_find_component (agent, stream_id, component_id, &stream,
2847           &component)) {
2848     ret = FALSE;
2849     goto done;
2850   }
2851
2852   length = g_list_length (component->turn_servers);
2853   if (length == NICE_CANDIDATE_MAX_TURN_SERVERS) {
2854     g_warning ("Agent %p : cannot have more than %d turn servers.",
2855         agent, length);
2856     ret = FALSE;
2857     goto done;
2858   }
2859
2860   turn = turn_server_new (server_ip, server_port, username, password, type);
2861
2862   if (!turn) {
2863     ret = FALSE;
2864     goto done;
2865   }
2866
2867   nice_debug ("Agent %p: added relay server [%s]:%d of type %d to s/c %d/%d "
2868       "with user/pass : %s -- %s", agent, server_ip, server_port, type,
2869       stream_id, component_id, username,
2870       nice_debug_is_verbose() ? password : "****");
2871
2872   /* The turn server preference (used to setup its priority in the
2873    * conncheck) is simply its position in the list. The preference must
2874    * be unique for each one.
2875    */
2876   turn->preference = length;
2877   component->turn_servers = g_list_append (component->turn_servers, turn);
2878
2879  if (stream->gathering_started) {
2880     GSList *i;
2881
2882     stream->gathering = TRUE;
2883
2884     for (i = component->local_candidates; i; i = i->next) {
2885       NiceCandidate *candidate = i->data;
2886
2887       if  (candidate->type == NICE_CANDIDATE_TYPE_HOST &&
2888            candidate->transport != NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE &&
2889           nice_address_ip_version (&candidate->addr) ==
2890           nice_address_ip_version (&turn->server))
2891         priv_add_new_candidate_discovery_turn (agent,
2892             candidate->sockptr, turn, stream, component_id,
2893             candidate->transport != NICE_CANDIDATE_TRANSPORT_UDP);
2894     }
2895
2896     if (agent->discovery_unsched_items)
2897       discovery_schedule (agent);
2898   }
2899
2900
2901  done:
2902
2903   agent_unlock_and_emit (agent);
2904   return ret;
2905 }
2906
2907 #ifdef HAVE_GUPNP
2908
2909 static void agent_check_upnp_gathering_done (NiceAgent *agent);
2910
2911 static gboolean priv_upnp_timeout_cb_agent_locked (NiceAgent *agent,
2912     gpointer user_data)
2913 {
2914   nice_debug ("Agent %p : UPnP port mapping timed out", agent);
2915
2916   /* We cannot free priv->upnp here as it may be holding mappings open which
2917    * we are using (e.g. if some mappings were successful and others errored). */
2918   g_slist_free_full (agent->upnp_mapping, (GDestroyNotify) nice_address_free);
2919   agent->upnp_mapping = NULL;
2920
2921   agent_check_upnp_gathering_done (agent);
2922
2923   return FALSE;
2924 }
2925
2926 /* Check whether UPnP gathering is done, which is true when the list of pending
2927  * mappings (upnp_mapping) is empty. When it is empty, we have heard back from
2928  * gupnp-igd about each of the mappings we added, either successfully or not.
2929  *
2930  * Note that upnp_mapping has to be a list, rather than a counter, as the
2931  * mapped-external-port and error-mapping-port signals could be emitted multiple
2932  * times for each mapping. */
2933 static void agent_check_upnp_gathering_done (NiceAgent *agent)
2934 {
2935   if (agent->upnp_mapping != NULL)
2936     return;
2937
2938   if (agent->upnp_timer_source != NULL) {
2939     g_source_destroy (agent->upnp_timer_source);
2940     g_source_unref (agent->upnp_timer_source);
2941     agent->upnp_timer_source = NULL;
2942   }
2943
2944   agent_gathering_done (agent);
2945 }
2946
2947 static void _upnp_mapped_external_port (GUPnPSimpleIgd *self, gchar *proto,
2948     gchar *external_ip, gchar *replaces_external_ip, guint external_port,
2949     gchar *local_ip, guint local_port, gchar *description, gpointer user_data)
2950 {
2951   NiceAgent *agent = (NiceAgent*)user_data;
2952   NiceAddress localaddr;
2953   NiceAddress externaddr;
2954   NiceCandidateTransport transport;
2955   GSList *i, *j, *k;
2956
2957   agent_lock (agent);
2958
2959   if (agent->upnp_timer_source == NULL)
2960     goto end;
2961
2962   nice_debug ("Agent %p : Successfully mapped %s:%d to %s:%d", agent, local_ip,
2963       local_port, external_ip, external_port);
2964
2965   if (!nice_address_set_from_string (&localaddr, local_ip))
2966     goto end;
2967   nice_address_set_port (&localaddr, local_port);
2968
2969   if (g_strcmp0 (proto, "TCP") == 0)
2970     transport = NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE;
2971   else
2972     transport = NICE_CANDIDATE_TRANSPORT_UDP;
2973
2974   for (i = agent->upnp_mapping; i; i = i->next) {
2975     NiceAddress *addr = i->data;
2976     if (nice_address_equal (&localaddr, addr)) {
2977       agent->upnp_mapping = g_slist_remove (agent->upnp_mapping, addr);
2978       nice_address_free (addr);
2979       break;
2980     }
2981   }
2982
2983   if (!nice_address_set_from_string (&externaddr, external_ip))
2984     goto end;
2985   nice_address_set_port (&externaddr, external_port);
2986
2987   for (i = agent->streams; i; i = i->next) {
2988     NiceStream *stream = i->data;
2989     for (j = stream->components; j; j = j->next) {
2990       NiceComponent *component = j->data;
2991       for (k = component->local_candidates; k; k = k->next) {
2992         NiceCandidate *local_candidate = k->data;
2993
2994         if (agent->force_relay &&
2995             local_candidate->type != NICE_CANDIDATE_TYPE_RELAYED)
2996           continue;
2997
2998         if (nice_address_equal (&localaddr, &local_candidate->base_addr)) {
2999           discovery_add_server_reflexive_candidate (
3000               agent,
3001               stream->id,
3002               component->id,
3003               &externaddr,
3004               transport,
3005               local_candidate->sockptr,
3006               TRUE);
3007           goto end;
3008         }
3009       }
3010     }
3011   }
3012
3013  end:
3014   agent_check_upnp_gathering_done (agent);
3015
3016   agent_unlock_and_emit (agent);
3017 }
3018
3019 static void _upnp_error_mapping_port (GUPnPSimpleIgd *self, GError *error,
3020     gchar *proto, guint external_port, gchar *local_ip, guint local_port,
3021     gchar *description, gpointer user_data)
3022 {
3023   NiceAgent *agent = (NiceAgent*)user_data;
3024   NiceAddress localaddr;
3025   GSList *i;
3026
3027   agent_lock (agent);
3028
3029   nice_debug ("Agent %p : Error mapping %s:%d to %d (%d) : %s", agent, local_ip,
3030       local_port, external_port, error->domain, error->message);
3031   if (nice_address_set_from_string (&localaddr, local_ip)) {
3032     nice_address_set_port (&localaddr, local_port);
3033
3034     for (i = agent->upnp_mapping; i; i = i->next) {
3035       NiceAddress *addr = i->data;
3036       if (nice_address_equal (&localaddr, addr)) {
3037         agent->upnp_mapping = g_slist_remove (agent->upnp_mapping, addr);
3038         nice_address_free (addr);
3039         break;
3040       }
3041     }
3042
3043     agent_check_upnp_gathering_done (agent);
3044   }
3045
3046   agent_unlock_and_emit (agent);
3047 }
3048
3049 #endif
3050
3051 NICEAPI_EXPORT gboolean
3052 nice_agent_gather_candidates (
3053   NiceAgent *agent,
3054   guint stream_id)
3055 {
3056   guint cid;
3057   GSList *i;
3058   NiceStream *stream;
3059   GSList *local_addresses = NULL;
3060   gboolean ret = TRUE;
3061   guint length;
3062
3063   g_return_val_if_fail (NICE_IS_AGENT (agent), FALSE);
3064   g_return_val_if_fail (stream_id >= 1, FALSE);
3065
3066   agent_lock (agent);
3067
3068   stream = agent_find_stream (agent, stream_id);
3069   if (stream == NULL) {
3070     agent_unlock_and_emit (agent);
3071     return FALSE;
3072   }
3073
3074   if (stream->gathering_started) {
3075     /* Stream is already gathering, ignore this call */
3076     agent_unlock_and_emit (agent);
3077     return TRUE;
3078   }
3079
3080   nice_debug ("Agent %p : In %s mode, starting candidate gathering.", agent,
3081       agent->full_mode ? "ICE-FULL" : "ICE-LITE");
3082
3083 #ifdef HAVE_GUPNP
3084   if (agent->upnp_enabled && agent->upnp == NULL && !agent->force_relay) {
3085     agent->upnp = gupnp_simple_igd_thread_new ();
3086
3087     if (agent->upnp) {
3088       g_signal_connect (agent->upnp, "mapped-external-port",
3089           G_CALLBACK (_upnp_mapped_external_port), agent);
3090       g_signal_connect (agent->upnp, "error-mapping-port",
3091           G_CALLBACK (_upnp_error_mapping_port), agent);
3092     } else {
3093       nice_debug ("Agent %p : Error creating UPnP Simple IGD agent", agent);
3094     }
3095   } else {
3096     nice_debug ("Agent %p : UPnP property Disabled", agent);
3097   }
3098 #else
3099   nice_debug ("Agent %p : libnice compiled without UPnP support", agent);
3100 #endif
3101
3102   /* if no local addresses added, generate them ourselves */
3103   if (agent->local_addresses == NULL) {
3104     GList *addresses = nice_interfaces_get_local_ips (FALSE);
3105     GList *item;
3106
3107     for (item = addresses; item; item = g_list_next (item)) {
3108       const gchar *addr_string = item->data;
3109       NiceAddress *addr = nice_address_new ();
3110
3111       if (nice_address_set_from_string (addr, addr_string)) {
3112         local_addresses = g_slist_append (local_addresses, addr);
3113       } else {
3114         nice_debug ("Error: Failed to parse local address â€˜%s’.", addr_string);
3115         nice_address_free (addr);
3116       }
3117     }
3118
3119     g_list_free_full (addresses, (GDestroyNotify) g_free);
3120   } else {
3121     for (i = agent->local_addresses; i; i = i->next) {
3122       NiceAddress *addr = i->data;
3123       NiceAddress *dupaddr = nice_address_dup (addr);
3124
3125       local_addresses = g_slist_append (local_addresses, dupaddr);
3126     }
3127   }
3128
3129   length = g_slist_length (local_addresses);
3130   if (length > NICE_CANDIDATE_MAX_LOCAL_ADDRESSES) {
3131     g_warning ("Agent %p : cannot have more than %d local addresses.",
3132         agent, NICE_CANDIDATE_MAX_LOCAL_ADDRESSES);
3133   }
3134
3135   for (cid = 1; cid <= stream->n_components; cid++) {
3136     NiceComponent *component = nice_stream_find_component_by_id (stream, cid);
3137     gboolean found_local_address = FALSE;
3138     enum {
3139       ADD_HOST_MIN = 0,
3140       ADD_HOST_UDP = ADD_HOST_MIN,
3141       ADD_HOST_TCP_ACTIVE,
3142       ADD_HOST_TCP_PASSIVE,
3143       ADD_HOST_MAX = ADD_HOST_TCP_PASSIVE
3144     } add_type;
3145
3146     if (component == NULL)
3147       continue;
3148
3149     /* generate a local host candidate for each local address */
3150     length = 0;
3151     for (i = local_addresses;
3152         i && length < NICE_CANDIDATE_MAX_LOCAL_ADDRESSES;
3153         i = i->next, length++) {
3154       NiceAddress *addr = i->data;
3155       NiceCandidate *host_candidate;
3156
3157 #ifdef HAVE_GUPNP
3158       gchar local_ip[NICE_ADDRESS_STRING_LEN];
3159       nice_address_to_string (addr, local_ip);
3160 #endif
3161
3162       for (add_type = ADD_HOST_MIN; add_type <= ADD_HOST_MAX; add_type++) {
3163         NiceCandidateTransport transport;
3164         guint current_port;
3165         guint start_port;
3166         HostCandidateResult res = HOST_CANDIDATE_CANT_CREATE_SOCKET;
3167
3168         if ((agent->use_ice_udp == FALSE && add_type == ADD_HOST_UDP) ||
3169             (agent->use_ice_tcp == FALSE && add_type != ADD_HOST_UDP))
3170           continue;
3171
3172         switch (add_type) {
3173           default:
3174           case ADD_HOST_UDP:
3175             transport = NICE_CANDIDATE_TRANSPORT_UDP;
3176             break;
3177           case ADD_HOST_TCP_ACTIVE:
3178             transport = NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE;
3179             break;
3180           case ADD_HOST_TCP_PASSIVE:
3181             transport = NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE;
3182             break;
3183         }
3184
3185         start_port = component->min_port;
3186         if(component->min_port != 0) {
3187           start_port = nice_rng_generate_int(agent->rng, component->min_port, component->max_port+1);
3188         }
3189         current_port = start_port;
3190
3191         host_candidate = NULL;
3192         while (res == HOST_CANDIDATE_CANT_CREATE_SOCKET ||
3193             res == HOST_CANDIDATE_DUPLICATE_PORT) {
3194           nice_debug ("Agent %p: Trying to create host candidate on port %d", agent, current_port);
3195           nice_address_set_port (addr, current_port);
3196           res =  discovery_add_local_host_candidate (agent, stream->id, cid,
3197               addr, transport, &host_candidate);
3198           if (current_port > 0)
3199             current_port++;
3200           if (current_port > component->max_port)
3201             current_port = component->min_port;
3202           if (current_port == start_port && res != HOST_CANDIDATE_DUPLICATE_PORT)
3203             break;
3204           if (current_port == 0 && res != HOST_CANDIDATE_DUPLICATE_PORT)
3205             break;
3206         }
3207
3208         if (res == HOST_CANDIDATE_REDUNDANT) {
3209           nice_debug ("Agent %p: Ignoring local candidate, it's redundant",
3210               agent);
3211           continue;
3212         } else if (res == HOST_CANDIDATE_FAILED) {
3213           nice_debug ("Agent %p: Could not retrieve component %d/%d", agent,
3214               stream->id, cid);
3215           continue;
3216         } else if (res == HOST_CANDIDATE_CANT_CREATE_SOCKET) {
3217           if (nice_debug_is_enabled ()) {
3218             gchar ip[NICE_ADDRESS_STRING_LEN];
3219             nice_address_to_string (addr, ip);
3220             nice_debug ("Agent %p: Unable to add local host candidate %s for"
3221                 " s%d:%d. Invalid interface?", agent, ip, stream->id,
3222                 component->id);
3223           }
3224           continue;
3225         } else if (res == HOST_CANDIDATE_DUPLICATE_PORT) {
3226           nice_debug ("Agent %p: Ignoring local candidate, duplicate port",
3227               agent);
3228           continue;
3229         }
3230
3231         found_local_address = TRUE;
3232         nice_address_set_port (addr, 0);
3233
3234         nice_socket_set_writable_callback (host_candidate->sockptr,
3235             _tcp_sock_is_writable, component);
3236
3237 #ifdef HAVE_GUPNP
3238       if (agent->upnp_enabled && agent->upnp &&
3239           transport != NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE) {
3240         NiceAddress *base_addr = nice_address_dup (&host_candidate->base_addr);
3241         nice_debug ("Agent %p: Adding UPnP port %s:%d", agent, local_ip,
3242             nice_address_get_port (base_addr));
3243         gupnp_simple_igd_add_port (GUPNP_SIMPLE_IGD (agent->upnp),
3244             transport == NICE_CANDIDATE_TRANSPORT_UDP ? "UDP" : "TCP",
3245             0, local_ip, nice_address_get_port (base_addr),
3246             0, PACKAGE_STRING);
3247         agent->upnp_mapping = g_slist_prepend (agent->upnp_mapping, base_addr);
3248
3249         agent_timeout_add_with_context (agent, &agent->upnp_timer_source,
3250             "UPnP timeout", agent->upnp_timeout,
3251             priv_upnp_timeout_cb_agent_locked, agent);
3252       }
3253 #endif
3254
3255         /* TODO: Add server-reflexive support for TCP candidates */
3256         if (agent->full_mode && agent->stun_server_ip && !agent->force_relay &&
3257             transport == NICE_CANDIDATE_TRANSPORT_UDP) {
3258           NiceAddress stun_server;
3259           if (nice_address_set_from_string (&stun_server, agent->stun_server_ip)) {
3260             nice_address_set_port (&stun_server, agent->stun_server_port);
3261
3262             if (nice_address_ip_version (&host_candidate->addr) ==
3263                 nice_address_ip_version (&stun_server))
3264               priv_add_new_candidate_discovery_stun (agent,
3265                   host_candidate->sockptr,
3266                   stun_server,
3267                   stream,
3268                   cid);
3269           }
3270         }
3271
3272         if (agent->full_mode && component &&
3273             transport != NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE) {
3274           GList *item;
3275           int host_ip_version = nice_address_ip_version (&host_candidate->addr);
3276
3277           for (item = component->turn_servers; item; item = item->next) {
3278             TurnServer *turn = item->data;
3279
3280             if (host_ip_version != nice_address_ip_version (&turn->server)) {
3281               continue;
3282             }
3283
3284             priv_add_new_candidate_discovery_turn (agent,
3285                 host_candidate->sockptr,
3286                 turn,
3287                 stream,
3288                 cid,
3289                 host_candidate->transport != NICE_CANDIDATE_TRANSPORT_UDP);
3290           }
3291         }
3292       }
3293     }
3294     /* Go to error if we could not find a local address for a given
3295      * component
3296      */
3297     if (!found_local_address) {
3298       ret = FALSE;
3299       goto error;
3300     }
3301   }
3302
3303   stream->gathering = TRUE;
3304   stream->gathering_started = TRUE;
3305
3306   /* Only signal the new candidates after we're sure that the gathering was
3307    * succesfful. But before sending gathering-done */
3308   for (cid = 1; cid <= stream->n_components; cid++) {
3309     NiceComponent *component = nice_stream_find_component_by_id (stream, cid);
3310     for (i = component->local_candidates; i; i = i->next) {
3311       NiceCandidate *candidate = i->data;
3312
3313       if (agent->force_relay && candidate->type != NICE_CANDIDATE_TYPE_RELAYED)
3314         continue;
3315
3316       agent_signal_new_candidate (agent, candidate);
3317     }
3318   }
3319
3320   /* note: no async discoveries pending, signal that we are ready */
3321   if (agent->discovery_unsched_items == 0 &&
3322 #ifdef HAVE_GUPNP
3323       agent->upnp_mapping == NULL) {
3324 #else
3325       TRUE) {
3326 #endif
3327     nice_debug ("Agent %p: Candidate gathering FINISHED, no scheduled items.",
3328         agent);
3329     agent_gathering_done (agent);
3330   } else if (agent->discovery_unsched_items) {
3331     discovery_schedule (agent);
3332   }
3333
3334  error:
3335   for (i = local_addresses; i; i = i->next)
3336     nice_address_free (i->data);
3337   g_slist_free (local_addresses);
3338
3339   if (ret == FALSE) {
3340     priv_stop_upnp (agent);
3341     for (cid = 1; cid <= stream->n_components; cid++) {
3342       NiceComponent *component = nice_stream_find_component_by_id (stream, cid);
3343
3344       nice_component_free_socket_sources (component);
3345
3346       for (i = component->local_candidates; i; i = i->next) {
3347         NiceCandidate *candidate = i->data;
3348
3349         agent_remove_local_candidate (agent, candidate);
3350
3351         nice_candidate_free (candidate);
3352       }
3353       g_slist_free (component->local_candidates);
3354       component->local_candidates = NULL;
3355     }
3356     discovery_prune_stream (agent, stream_id);
3357   }
3358
3359   agent_unlock_and_emit (agent);
3360
3361   return ret;
3362 }
3363
3364 void agent_remove_local_candidate (NiceAgent *agent, NiceCandidate *candidate)
3365 {
3366 #ifdef HAVE_GUPNP
3367   gchar local_ip[NICE_ADDRESS_STRING_LEN];
3368
3369   if (agent->upnp == NULL)
3370     return;
3371
3372   if (candidate->type != NICE_CANDIDATE_TYPE_HOST)
3373     return;
3374
3375   if (nice_address_get_port (&candidate->addr) == 0)
3376     return;
3377
3378   nice_address_to_string (&candidate->addr, local_ip);
3379
3380   gupnp_simple_igd_remove_port_local (GUPNP_SIMPLE_IGD (agent->upnp), "UDP",
3381       local_ip, nice_address_get_port (&candidate->addr));
3382 #endif
3383 }
3384
3385 static void priv_stop_upnp (NiceAgent *agent)
3386 {
3387 #ifdef HAVE_GUPNP
3388   if (!agent->upnp)
3389     return;
3390
3391   g_slist_free_full (agent->upnp_mapping, (GDestroyNotify) nice_address_free);
3392   agent->upnp_mapping = NULL;
3393
3394   if (agent->upnp_timer_source != NULL) {
3395     g_source_destroy (agent->upnp_timer_source);
3396     g_source_unref (agent->upnp_timer_source);
3397     agent->upnp_timer_source = NULL;
3398   }
3399 #endif
3400 }
3401
3402 static void priv_remove_keepalive_timer (NiceAgent *agent)
3403 {
3404   if (agent->keepalive_timer_source != NULL) {
3405     g_source_destroy (agent->keepalive_timer_source);
3406     g_source_unref (agent->keepalive_timer_source);
3407     agent->keepalive_timer_source = NULL;
3408   }
3409 }
3410
3411 static gboolean
3412 on_stream_refreshes_pruned (NiceAgent *agent, NiceStream *stream)
3413 {
3414   // This is called from a timeout cb with agent lock held
3415
3416   nice_stream_close (agent, stream);
3417
3418   agent->pruning_streams = g_slist_remove (agent->pruning_streams, stream);
3419
3420   agent_unlock (agent);
3421
3422   /* Actually free the stream. This should be done with the lock released, as
3423    * it could end up disposing of a NiceIOStream, which tries to take the
3424    * agent lock itself. */
3425   g_object_unref (stream);
3426
3427   agent_lock (agent);
3428
3429   return G_SOURCE_REMOVE;
3430 }
3431
3432 NICEAPI_EXPORT void
3433 nice_agent_remove_stream (
3434   NiceAgent *agent,
3435   guint stream_id)
3436 {
3437   guint stream_ids[] = { stream_id, 0 };
3438
3439   /* note that streams/candidates can be in use by other threads */
3440
3441   NiceStream *stream;
3442
3443   g_return_if_fail (NICE_IS_AGENT (agent));
3444   g_return_if_fail (stream_id >= 1);
3445
3446   agent_lock (agent);
3447   stream = agent_find_stream (agent, stream_id);
3448
3449   if (!stream) {
3450     agent_unlock_and_emit (agent);
3451     return;
3452   }
3453
3454   /* note: remove items with matching stream_ids from both lists */
3455   conn_check_prune_stream (agent, stream);
3456   discovery_prune_stream (agent, stream_id);
3457   refresh_prune_stream_async (agent, stream,
3458       (NiceTimeoutLockedCallback) on_stream_refreshes_pruned);
3459
3460   agent->pruning_streams = g_slist_prepend (agent->pruning_streams, stream);
3461
3462   /* Remove the stream and signal its removal. */
3463   agent->streams = g_slist_remove (agent->streams, stream);
3464
3465   if (!agent->streams)
3466     priv_remove_keepalive_timer (agent);
3467
3468   agent_queue_signal (agent, signals[SIGNAL_STREAMS_REMOVED],
3469       g_memdup (stream_ids, sizeof(stream_ids)));
3470
3471   agent_unlock_and_emit (agent);
3472 }
3473
3474 NICEAPI_EXPORT void
3475 nice_agent_set_port_range (NiceAgent *agent, guint stream_id, guint component_id,
3476     guint min_port, guint max_port)
3477 {
3478   NiceStream *stream;
3479   NiceComponent *component;
3480
3481   g_return_if_fail (NICE_IS_AGENT (agent));
3482   g_return_if_fail (stream_id >= 1);
3483   g_return_if_fail (component_id >= 1);
3484
3485   agent_lock (agent);
3486
3487   if (agent_find_component (agent, stream_id, component_id, &stream,
3488           &component)) {
3489     if (stream->gathering_started) {
3490       g_critical ("nice_agent_gather_candidates (stream_id=%u) already called for this stream", stream_id);
3491     } else {
3492       component->min_port = min_port;
3493       component->max_port = max_port;
3494     }
3495   }
3496
3497   agent_unlock_and_emit (agent);
3498 }
3499
3500 NICEAPI_EXPORT gboolean
3501 nice_agent_add_local_address (NiceAgent *agent, NiceAddress *addr)
3502 {
3503   NiceAddress *dupaddr;
3504
3505   g_return_val_if_fail (NICE_IS_AGENT (agent), FALSE);
3506   g_return_val_if_fail (addr != NULL, FALSE);
3507
3508   agent_lock (agent);
3509
3510   dupaddr = nice_address_dup (addr);
3511   nice_address_set_port (dupaddr, 0);
3512   agent->local_addresses = g_slist_append (agent->local_addresses, dupaddr);
3513
3514   agent_unlock_and_emit (agent);
3515   return TRUE;
3516 }
3517
3518 /* Recompute foundations of all candidate pairs from a given stream
3519  * having a specific remote candidate, and eventually update the
3520  * priority of the selected pair as well.
3521  */
3522 static void priv_update_pair_foundations (NiceAgent *agent,
3523     guint stream_id, guint component_id, NiceCandidate *remote)
3524 {
3525   NiceStream *stream;
3526   NiceComponent *component;
3527
3528   if (agent_find_component (agent, stream_id, component_id, &stream,
3529       &component)) {
3530     GSList *i;
3531
3532     for (i = stream->conncheck_list; i; i = i->next) {
3533       CandidateCheckPair *pair = i->data;
3534
3535       if (pair->remote == remote) {
3536         gchar foundation[NICE_CANDIDATE_PAIR_MAX_FOUNDATION];
3537         g_snprintf (foundation, NICE_CANDIDATE_PAIR_MAX_FOUNDATION, "%s:%s",
3538             pair->local->foundation, pair->remote->foundation);
3539         if (strncmp (pair->foundation, foundation,
3540             NICE_CANDIDATE_PAIR_MAX_FOUNDATION)) {
3541           g_strlcpy (pair->foundation, foundation,
3542               NICE_CANDIDATE_PAIR_MAX_FOUNDATION);
3543           nice_debug ("Agent %p : Updating pair %p foundation to '%s'",
3544               agent, pair, pair->foundation);
3545           if (pair->state == NICE_CHECK_SUCCEEDED)
3546             conn_check_unfreeze_related (agent, pair);
3547           if (component->selected_pair.local == pair->local &&
3548               component->selected_pair.remote == pair->remote) {
3549             gchar priority[NICE_CANDIDATE_PAIR_PRIORITY_MAX_SIZE];
3550
3551             /* the foundation update of the selected pair also implies
3552              * an update of its priority. stun_priority doesn't change
3553              * because only the remote candidate foundation is modified.
3554              */
3555             nice_debug ("Agent %p : pair %p is the selected pair, updating "
3556                 "its priority.", agent, pair);
3557             component->selected_pair.priority = pair->priority;
3558
3559             nice_candidate_pair_priority_to_string (pair->priority, priority);
3560             nice_debug ("Agent %p : updating SELECTED PAIR for component "
3561                 "%u: %s (prio:%s).", agent,
3562                 component->id, foundation, priority);
3563             agent_signal_new_selected_pair (agent, pair->stream_id,
3564               component->id, pair->local, pair->remote);
3565           }
3566         }
3567       }
3568     }
3569   }
3570 }
3571
3572 /* Returns the nominated pair with the highest priority.
3573  */
3574 static CandidateCheckPair *priv_get_highest_priority_nominated_pair (
3575     NiceAgent *agent, guint stream_id, guint component_id)
3576 {
3577   NiceStream *stream;
3578   NiceComponent *component;
3579   CandidateCheckPair *pair;
3580   GSList *i;
3581
3582   if (agent_find_component (agent, stream_id, component_id, &stream,
3583       &component)) {
3584
3585     for (i = stream->conncheck_list; i; i = i->next) {
3586       pair = i->data;
3587       if (pair->component_id == component_id && pair->nominated) {
3588         return pair;
3589       }
3590     }
3591   }
3592   return NULL;
3593 }
3594
3595 static gboolean priv_add_remote_candidate (
3596   NiceAgent *agent,
3597   guint stream_id,
3598   guint component_id,
3599   NiceCandidateType type,
3600   const NiceAddress *addr,
3601   const NiceAddress *base_addr,
3602   NiceCandidateTransport transport,
3603   guint32 priority,
3604   const gchar *username,
3605   const gchar *password,
3606   const gchar *foundation)
3607 {
3608   NiceStream *stream;
3609   NiceComponent *component;
3610   NiceCandidate *candidate;
3611   CandidateCheckPair *pair;
3612
3613   if (transport == NICE_CANDIDATE_TRANSPORT_UDP &&
3614       !agent->use_ice_udp)
3615     return FALSE;
3616   if (transport != NICE_CANDIDATE_TRANSPORT_UDP &&
3617       !agent->use_ice_tcp)
3618     return FALSE;
3619
3620   if (!agent_find_component (agent, stream_id, component_id, &stream,
3621       &component))
3622     return FALSE;
3623
3624   /* step: check whether the candidate already exists */
3625   candidate = nice_component_find_remote_candidate (component, addr, transport);
3626
3627   /* If it was a discovered remote peer reflexive candidate, then it should
3628    * be updated according to RFC 5245 section 7.2.1.3 */
3629   if (candidate && candidate->type == NICE_CANDIDATE_TYPE_PEER_REFLEXIVE) {
3630     nice_debug ("Agent %p : Updating existing peer-rfx remote candidate to %s",
3631         agent, _cand_type_to_sdp (type));
3632     candidate->type = type;
3633     /* The updated candidate is no more peer reflexive, so its
3634      * sockptr can be cleared
3635      */
3636     candidate->sockptr = NULL;
3637     /* If it got there, the next one will also be ran, so the foundation
3638      * will be set.
3639      */
3640   }
3641
3642   if (candidate && candidate->type == type) {
3643     if (nice_debug_is_enabled ()) {
3644       gchar tmpbuf[INET6_ADDRSTRLEN];
3645       nice_address_to_string (addr, tmpbuf);
3646       nice_debug ("Agent %p : Updating existing remote candidate with addr [%s]:%u"
3647           " for s%d/c%d. U/P '%s'/'%s' prio: %08x", agent, tmpbuf,
3648           nice_address_get_port (addr), stream_id, component_id,
3649           username, password, priority);
3650     }
3651     /* case 1: an existing candidate, update the attributes */
3652     if (base_addr)
3653       candidate->base_addr = *base_addr;
3654     candidate->priority = priority;
3655     if (foundation)
3656       g_strlcpy(candidate->foundation, foundation,
3657           NICE_CANDIDATE_MAX_FOUNDATION);
3658     /* note: username and password must remain the same during
3659      *       a session; see sect 9.1.2 in ICE ID-19 */
3660
3661     /* note: however, the user/pass in ID-19 is global, if the user/pass
3662      * are set in the candidate here, it means they need to be updated...
3663      * this is essential to overcome a race condition where we might receive
3664      * a valid binding request from a valid candidate that wasn't yet added to
3665      * our list of candidates.. this 'update' will make the peer-rflx a
3666      * server-rflx/host candidate again */
3667     if (username) {
3668       if (candidate->username == NULL)
3669         candidate->username = g_strdup (username);
3670       else if (g_strcmp0 (username, candidate->username))
3671         nice_debug ("Agent %p : Candidate username '%s' is not allowed "
3672             "to change to '%s' now (ICE restart only).", agent,
3673             candidate->username, username);
3674     }
3675     if (password) {
3676       if (candidate->password == NULL)
3677         candidate->password = g_strdup (password);
3678       else if (g_strcmp0 (password, candidate->password))
3679         nice_debug ("Agent %p : candidate password '%s' is not allowed "
3680             "to change to '%s' now (ICE restart only).", agent,
3681             candidate->password, password);
3682     }
3683
3684     /* since the type of the existing candidate may have changed,
3685      * the pairs priority and foundation related to this candidate need
3686      * to be recomputed...
3687      */
3688     recalculate_pair_priorities (agent);
3689     priv_update_pair_foundations (agent, stream_id, component_id, candidate);
3690     /* ... and maybe we now have another nominated pair with a higher
3691      * priority as the result of this priorities update.
3692      */
3693     pair = priv_get_highest_priority_nominated_pair (agent,
3694         stream_id, component_id);
3695     if (pair &&
3696         (pair->local != component->selected_pair.local ||
3697          pair->remote != component->selected_pair.remote)) {
3698       /* If we have (at least) one pair with the nominated flag set, it
3699        * implies that this pair (or another) is set as the selected pair
3700        * for this component. In other words, this is really an *update*
3701        * of the selected pair.
3702        */
3703       g_assert (component->selected_pair.local != NULL);
3704       g_assert (component->selected_pair.remote != NULL);
3705       nice_debug ("Agent %p : Updating selected pair with higher "
3706           "priority nominated pair %p.", agent, pair);
3707       conn_check_update_selected_pair (agent, component, pair);
3708     }
3709     conn_check_update_check_list_state_for_ready (agent, stream, component);
3710   }
3711   else {
3712     /* case 2: add a new candidate */
3713
3714     if (type == NICE_CANDIDATE_TYPE_PEER_REFLEXIVE) {
3715       nice_debug("Agent %p : Warning: ignoring externally set peer-reflexive candidate!", agent);
3716       return FALSE;
3717     }
3718     candidate = nice_candidate_new (type);
3719
3720     candidate->stream_id = stream_id;
3721     candidate->component_id = component_id;
3722
3723     candidate->type = type;
3724     if (addr)
3725       candidate->addr = *addr;
3726
3727     if (nice_debug_is_enabled ()) {
3728       gchar tmpbuf[INET6_ADDRSTRLEN] = {0};
3729       if (addr)
3730         nice_address_to_string (addr, tmpbuf);
3731       nice_debug ("Agent %p : Adding %s remote candidate with addr [%s]:%u"
3732           " for s%d/c%d. U/P '%s'/'%s' prio: %08x", agent,
3733           _transport_to_string (transport), tmpbuf,
3734           addr? nice_address_get_port (addr) : 0, stream_id, component_id,
3735           username, password, priority);
3736     }
3737
3738     if (NICE_AGENT_IS_COMPATIBLE_WITH_RFC5245_OR_OC2007R2 (agent)) {
3739       /* note:  If there are TCP candidates for a media stream,
3740        * a controlling agent MUST use the regular selection algorithm,
3741        * RFC 6544, sect 8, "Concluding ICE Processing"
3742        */
3743       if (agent->controlling_mode &&
3744           agent->nomination_mode == NICE_NOMINATION_MODE_AGGRESSIVE &&
3745           transport != NICE_CANDIDATE_TRANSPORT_UDP) {
3746         if (conn_check_stun_transactions_count (agent) > 0) {
3747           /* changing nomination mode from aggressive to regular while
3748            * conncheck is ongoing may cause unexpected results (inflight
3749            * aggressive stun requests may nominate a pair unilaterally)
3750            */
3751           nice_debug ("Agent %p : we have a TCP candidate, but conncheck "
3752               "has started already in aggressive mode, ignore it", agent);
3753           goto errors;
3754         } else {
3755           nice_debug ("Agent %p : we have a TCP candidate, switching back "
3756               "to regular nomination mode", agent);
3757           agent->nomination_mode = NICE_NOMINATION_MODE_REGULAR;
3758         }
3759       }
3760     }
3761
3762     if (base_addr)
3763       candidate->base_addr = *base_addr;
3764
3765     candidate->transport = transport;
3766     candidate->priority = priority;
3767     candidate->username = g_strdup (username);
3768     candidate->password = g_strdup (password);
3769
3770     if (foundation)
3771       g_strlcpy (candidate->foundation, foundation,
3772           NICE_CANDIDATE_MAX_FOUNDATION);
3773
3774     /* We only create a pair when a candidate is new, and not when
3775      * updating an existing one.
3776      */
3777     if (conn_check_add_for_candidate (agent, stream_id,
3778         component, candidate) < 0)
3779       goto errors;
3780
3781     component->remote_candidates = g_slist_append (component->remote_candidates,
3782         candidate);
3783   }
3784   return TRUE;
3785
3786 errors:
3787   nice_candidate_free (candidate);
3788   return FALSE;
3789 }
3790
3791 NICEAPI_EXPORT gboolean
3792 nice_agent_set_remote_credentials (
3793   NiceAgent *agent,
3794   guint stream_id,
3795   const gchar *ufrag, const gchar *pwd)
3796 {
3797   NiceStream *stream;
3798   gboolean ret = FALSE;
3799
3800   g_return_val_if_fail (NICE_IS_AGENT (agent), FALSE);
3801   g_return_val_if_fail (stream_id >= 1, FALSE);
3802
3803   nice_debug ("Agent %p: set_remote_credentials %d", agent, stream_id);
3804
3805   agent_lock (agent);
3806
3807   stream = agent_find_stream (agent, stream_id);
3808   /* note: oddly enough, ufrag and pwd can be empty strings */
3809   if (stream && ufrag && pwd) {
3810
3811     g_strlcpy (stream->remote_ufrag, ufrag, NICE_STREAM_MAX_UFRAG);
3812     g_strlcpy (stream->remote_password, pwd, NICE_STREAM_MAX_PWD);
3813
3814     conn_check_remote_credentials_set(agent, stream);
3815
3816     ret = TRUE;
3817     goto done;
3818   }
3819
3820  done:
3821   agent_unlock_and_emit (agent);
3822   return ret;
3823 }
3824
3825 NICEAPI_EXPORT gboolean
3826 nice_agent_set_local_credentials (
3827   NiceAgent *agent,
3828   guint stream_id,
3829   const gchar *ufrag,
3830   const gchar *pwd)
3831 {
3832   NiceStream *stream;
3833   gboolean ret = FALSE;
3834
3835   g_return_val_if_fail (NICE_IS_AGENT (agent), FALSE);
3836   g_return_val_if_fail (stream_id >= 1, FALSE);
3837
3838   agent_lock (agent);
3839
3840   stream = agent_find_stream (agent, stream_id);
3841
3842   /* note: oddly enough, ufrag and pwd can be empty strings */
3843   if (stream && ufrag && pwd) {
3844     g_strlcpy (stream->local_ufrag, ufrag, NICE_STREAM_MAX_UFRAG);
3845     g_strlcpy (stream->local_password, pwd, NICE_STREAM_MAX_PWD);
3846
3847     ret = TRUE;
3848     goto done;
3849   }
3850
3851  done:
3852   agent_unlock_and_emit (agent);
3853   return ret;
3854 }
3855
3856
3857 NICEAPI_EXPORT gboolean
3858 nice_agent_get_local_credentials (
3859   NiceAgent *agent,
3860   guint stream_id,
3861   gchar **ufrag, gchar **pwd)
3862 {
3863   NiceStream *stream;
3864   gboolean ret = TRUE;
3865
3866   g_return_val_if_fail (NICE_IS_AGENT (agent), FALSE);
3867   g_return_val_if_fail (stream_id >= 1, FALSE);
3868
3869   agent_lock (agent);
3870
3871   stream = agent_find_stream (agent, stream_id);
3872   if (stream == NULL) {
3873     goto done;
3874   }
3875
3876   if (!ufrag || !pwd) {
3877     goto done;
3878   }
3879
3880   *ufrag = g_strdup (stream->local_ufrag);
3881   *pwd = g_strdup (stream->local_password);
3882   ret = TRUE;
3883
3884  done:
3885
3886   agent_unlock_and_emit (agent);
3887   return ret;
3888 }
3889
3890 static int
3891 _set_remote_candidates_locked (NiceAgent *agent, NiceStream *stream,
3892     NiceComponent *component, const GSList *candidates)
3893 {
3894   const GSList *i;
3895   int added = 0;
3896
3897   for (i = candidates; i && added >= 0; i = i->next) {
3898     NiceCandidate *d = (NiceCandidate*) i->data;
3899
3900     if (nice_address_is_valid (&d->addr) == TRUE) {
3901       gboolean res =
3902           priv_add_remote_candidate (agent,
3903               stream->id,
3904               component->id,
3905               d->type,
3906               &d->addr,
3907               &d->base_addr,
3908               d->transport,
3909               d->priority,
3910               d->username,
3911               d->password,
3912               d->foundation);
3913       if (res)
3914         ++added;
3915     }
3916   }
3917
3918   if (added > 0) {
3919     conn_check_remote_candidates_set(agent, stream, component);
3920     conn_check_schedule_next (agent);
3921   }
3922
3923   return added;
3924 }
3925
3926
3927 NICEAPI_EXPORT int
3928 nice_agent_set_remote_candidates (NiceAgent *agent, guint stream_id, guint component_id, const GSList *candidates)
3929 {
3930   int added = 0;
3931   NiceStream *stream;
3932   NiceComponent *component;
3933
3934   g_return_val_if_fail (NICE_IS_AGENT (agent), 0);
3935   g_return_val_if_fail (stream_id >= 1, 0);
3936   g_return_val_if_fail (component_id >= 1, 0);
3937
3938   nice_debug ("Agent %p: set_remote_candidates %d %d", agent, stream_id, component_id);
3939
3940   agent_lock (agent);
3941
3942   if (!agent_find_component (agent, stream_id, component_id,
3943           &stream, &component)) {
3944     g_warning ("Could not find component %u in stream %u", component_id,
3945         stream_id);
3946     added = -1;
3947     goto done;
3948   }
3949
3950   added = _set_remote_candidates_locked (agent, stream, component, candidates);
3951
3952  done:
3953   agent_unlock_and_emit (agent);
3954
3955   return added;
3956 }
3957
3958 /* Return values for agent_recv_message_unlocked(). Needed purely because it
3959  * must differentiate between RECV_OOB and RECV_SUCCESS. */
3960 typedef enum {
3961   RECV_ERROR = -2,
3962   RECV_WOULD_BLOCK = -1,
3963   RECV_OOB = 0,
3964   RECV_SUCCESS = 1,
3965 } RecvStatus;
3966
3967 /*
3968  * agent_recv_message_unlocked:
3969  * @agent: a #NiceAgent
3970  * @stream: the stream to receive from
3971  * @component: the component to receive from
3972  * @socket: the socket to receive on
3973  * @message: the message to write into (must have at least 65536 bytes of buffer
3974  * space)
3975  *
3976  * Receive a single message of data from the given @stream, @component and
3977  * @socket tuple, in a non-blocking fashion. The caller must ensure that
3978  * @message contains enough buffers to provide at least 65536 bytes of buffer
3979  * space, but the buffers may be split as the caller sees fit.
3980  *
3981  * This must be called with the agent’s lock held.
3982  *
3983  * Returns: number of valid messages received on success (i.e. %RECV_SUCCESS or
3984  * 1), %RECV_OOB if data was successfully received but was handled out-of-band
3985  * (e.g. due to being a STUN control packet), %RECV_WOULD_BLOCK if no data is
3986  * available and the call would block, or %RECV_ERROR on error
3987  */
3988 static RecvStatus
3989 agent_recv_message_unlocked (
3990   NiceAgent *agent,
3991   NiceStream *stream,
3992   NiceComponent *component,
3993   NiceSocket *nicesock,
3994   NiceInputMessage *message)
3995 {
3996   NiceAddress from;
3997   GList *item;
3998   RecvStatus retval;
3999   gint sockret;
4000   gboolean is_turn = FALSE;
4001
4002   /* We need an address for packet parsing, below. */
4003   if (message->from == NULL) {
4004     message->from = &from;
4005   }
4006
4007   /* ICE-TCP requires that all packets be framed with RFC4571 */
4008   if (nice_socket_is_reliable (nicesock)) {
4009     /* In the case of OC2007 and OC2007R2 which uses UDP TURN for TCP-ACTIVE
4010      * and TCP-PASSIVE candidates, the recv_messages will be packetized and
4011      * always return an entire frame, so we must read it as is */
4012     if (nicesock->type == NICE_SOCKET_TYPE_UDP_TURN_OVER_TCP ||
4013         nicesock->type == NICE_SOCKET_TYPE_UDP_TURN) {
4014       GSList *cand_i;
4015       GInputVector *local_bufs;
4016       NiceInputMessage local_message;
4017       guint n_bufs = 0;
4018       guint16 rfc4571_frame;
4019       guint i;
4020
4021       /* In case of ICE-TCP on UDP-TURN (OC2007 compat), we need to do the recv
4022        * on the UDP_TURN socket, but it's possible we receive the source event
4023        * on the UDP_TURN_OVER_TCP socket, so in that case, we need to replace
4024        * the socket we do the recv on to the topmost socket
4025        */
4026       for (cand_i = component->local_candidates; cand_i; cand_i = cand_i->next) {
4027         NiceCandidate *cand = cand_i->data;
4028
4029         if (cand->type == NICE_CANDIDATE_TYPE_RELAYED &&
4030             cand->stream_id == stream->id &&
4031             cand->component_id == component->id &&
4032             nice_socket_is_based_on(cand->sockptr, nicesock)) {
4033           nice_debug ("Agent %p : Packet received from a TURN socket.",
4034               agent);
4035           nicesock = cand->sockptr;
4036           break;
4037         }
4038       }
4039       /* Count the number of buffers. */
4040       if (message->n_buffers == -1) {
4041         for (i = 0; message->buffers[i].buffer != NULL; i++)
4042           n_bufs++;
4043       } else {
4044         n_bufs = message->n_buffers;
4045       }
4046
4047       local_bufs = g_alloca ((n_bufs + 1) * sizeof (GInputVector));
4048       local_message.buffers = local_bufs;
4049       local_message.n_buffers = n_bufs + 1;
4050       local_message.from = message->from;
4051       local_message.length = 0;
4052
4053       local_bufs[0].buffer = &rfc4571_frame;
4054       local_bufs[0].size = sizeof (guint16);
4055
4056       for (i = 0; i < n_bufs; i++) {
4057         local_bufs[i + 1].buffer = message->buffers[i].buffer;
4058         local_bufs[i + 1].size = message->buffers[i].size;
4059       }
4060       sockret = nice_socket_recv_messages (nicesock, &local_message, 1);
4061       if (sockret == 1 && local_message.length >= sizeof (guint16)) {
4062         message->length = ntohs (rfc4571_frame);
4063       }
4064     } else {
4065       if (nicesock->type == NICE_SOCKET_TYPE_TCP_PASSIVE) {
4066         NiceSocket *new_socket;
4067
4068         /* Passive candidates when readable should accept and create a new
4069          * socket. When established, the connchecks will create a peer reflexive
4070          * candidate for it */
4071         new_socket = nice_tcp_passive_socket_accept (nicesock);
4072         if (new_socket) {
4073           _priv_set_socket_tos (agent, new_socket, stream->tos);
4074           nice_debug ("Agent %p: add to tcp-pass socket %p a new "
4075               "tcp accept socket %p in s/c %d/%d",
4076               agent, nicesock, new_socket, stream->id, component->id);
4077           nice_component_attach_socket (component, new_socket);
4078         }
4079         sockret = 0;
4080       } else {
4081         /* In the case of a real ICE-TCP connection, we can use the socket as a
4082          * bytestream and do the read here with caching of data being read
4083          */
4084         gssize available = g_socket_get_available_bytes (nicesock->fileno);
4085
4086         /* TODO: Support bytestream reads */
4087         message->length = 0;
4088         sockret = 0;
4089         if (available <= 0) {
4090           sockret = available;
4091
4092           /* If we don't call check_connect_result on an outbound connection,
4093            * then is_connected will always return FALSE. That's why we check
4094            * both conditions to make sure g_socket_is_connected returns the
4095            * correct result, otherwise we end up closing valid connections
4096            */
4097           if (g_socket_check_connect_result (nicesock->fileno, NULL) == FALSE ||
4098               g_socket_is_connected (nicesock->fileno) == FALSE) {
4099             /* If we receive a readable event on a TCP_BSD socket which is
4100              * not connected, it means that it failed to connect, so we must
4101              * return an error to make the socket fail/closed
4102              */
4103             sockret = -1;
4104           } else {
4105             gint flags = G_SOCKET_MSG_PEEK;
4106
4107             /* If available bytes are 0, but the socket is still considered
4108              * connected, then either we're just trying to see if there's more
4109              * data available or the peer closed the connection.
4110              * The only way to know is to do a read, so we do here a peek and
4111              * check the return value, if it's 0, it means the peer has closed
4112              * the connection, so we must return an error instead of WOULD_BLOCK
4113              */
4114             if (g_socket_receive_message (nicesock->fileno, NULL,
4115                     NULL, 0, NULL, NULL, &flags, NULL, NULL) == 0)
4116               sockret = -1;
4117           }
4118         } else if (agent->rfc4571_expecting_length == 0) {
4119           if ((gsize) available >= sizeof(guint16)) {
4120             guint16 rfc4571_frame;
4121             GInputVector local_buf = { &rfc4571_frame, sizeof(guint16)};
4122             NiceInputMessage local_message = { &local_buf, 1, message->from, 0};
4123
4124             sockret = nice_socket_recv_messages (nicesock, &local_message, 1);
4125             if (sockret == 1 && local_message.length >= sizeof (guint16)) {
4126               agent->rfc4571_expecting_length = ntohs (rfc4571_frame);
4127               available = g_socket_get_available_bytes (nicesock->fileno);
4128             }
4129           }
4130         }
4131         if (agent->rfc4571_expecting_length > 0 &&
4132             available >= agent->rfc4571_expecting_length) {
4133           GInputVector *local_bufs;
4134           NiceInputMessage local_message;
4135           gsize off;
4136           guint n_bufs = 0;
4137           guint i;
4138
4139           /* Count the number of buffers. */
4140           if (message->n_buffers == -1) {
4141             for (i = 0; message->buffers[i].buffer != NULL; i++)
4142               n_bufs++;
4143           } else {
4144             n_bufs = message->n_buffers;
4145           }
4146
4147           local_bufs = g_alloca (n_bufs * sizeof (GInputVector));
4148           local_message.buffers = local_bufs;
4149           local_message.from = message->from;
4150           local_message.length = 0;
4151           local_message.n_buffers = 0;
4152
4153           /* Only read up to the expected number of bytes in the frame */
4154           off = 0;
4155           for (i = 0; i < n_bufs; i++) {
4156             if (message->buffers[i].size < agent->rfc4571_expecting_length - off) {
4157               local_bufs[i].buffer = message->buffers[i].buffer;
4158               local_bufs[i].size = message->buffers[i].size;
4159               local_message.n_buffers++;
4160               off += message->buffers[i].size;
4161             } else {
4162               local_bufs[i].buffer = message->buffers[i].buffer;
4163               local_bufs[i].size = MIN (message->buffers[i].size,
4164                   agent->rfc4571_expecting_length - off);
4165               local_message.n_buffers++;
4166               off += local_bufs[i].size;
4167             }
4168           }
4169           sockret = nice_socket_recv_messages (nicesock, &local_message, 1);
4170           if (sockret == 1) {
4171             message->length = local_message.length;
4172             agent->rfc4571_expecting_length -= local_message.length;
4173           }
4174         }
4175       }
4176     }
4177   } else {
4178     sockret = nice_socket_recv_messages (nicesock, message, 1);
4179   }
4180
4181   if (sockret == 0) {
4182     retval = RECV_WOULD_BLOCK;  /* EWOULDBLOCK */
4183     nice_debug_verbose ("%s: Agent %p: no message available on read attempt",
4184         G_STRFUNC, agent);
4185     goto done;
4186   } else if (sockret < 0) {
4187     nice_debug ("Agent %p: %s returned %d, errno (%d) : %s",
4188         agent, G_STRFUNC, sockret, errno, g_strerror (errno));
4189
4190     retval = RECV_ERROR;
4191     goto done;
4192   } else {
4193     retval = sockret;
4194   }
4195
4196   g_assert_cmpint (retval, !=, RECV_OOB);
4197   if (message->length == 0) {
4198     retval = RECV_OOB;
4199     nice_debug_verbose ("%s: Agent %p: message handled out-of-band", G_STRFUNC,
4200         agent);
4201     goto done;
4202   }
4203
4204   if (nice_debug_is_verbose ()) {
4205     gchar tmpbuf[INET6_ADDRSTRLEN];
4206     nice_address_to_string (message->from, tmpbuf);
4207     nice_debug_verbose ("%s: Agent %p : Packet received on local socket %p "
4208         "(fd %d) from [%s]:%u (%" G_GSSIZE_FORMAT " octets).", G_STRFUNC, agent,
4209         nicesock, nicesock->fileno ? g_socket_get_fd (nicesock->fileno) : -1, tmpbuf,
4210         nice_address_get_port (message->from), message->length);
4211   }
4212
4213   if (nicesock->type == NICE_SOCKET_TYPE_UDP_TURN)
4214     is_turn = TRUE;
4215
4216   if (!is_turn && component->turn_candidate &&
4217       nice_socket_is_based_on (component->turn_candidate->sockptr, nicesock) &&
4218       nice_address_equal (message->from,
4219           &component->turn_candidate->turn->server)) {
4220     is_turn = TRUE;
4221     retval = nice_udp_turn_socket_parse_recv_message (
4222         component->turn_candidate->sockptr, &nicesock, message);
4223   }
4224
4225   for (item = component->turn_servers; item && !is_turn;
4226        item = g_list_next (item)) {
4227     TurnServer *turn = item->data;
4228     GSList *i = NULL;
4229
4230     if (!nice_address_equal (message->from, &turn->server))
4231       continue;
4232
4233     nice_debug_verbose ("Agent %p : Packet received from TURN server candidate.",
4234         agent);
4235     is_turn = TRUE;
4236
4237     for (i = component->local_candidates; i; i = i->next) {
4238       NiceCandidate *cand = i->data;
4239
4240       if (cand->type == NICE_CANDIDATE_TYPE_RELAYED &&
4241           cand->turn == turn &&
4242           cand->stream_id == stream->id &&
4243           nice_socket_is_based_on (cand->sockptr, nicesock)) {
4244         retval = nice_udp_turn_socket_parse_recv_message (cand->sockptr, &nicesock,
4245             message);
4246         break;
4247       }
4248     }
4249     break;
4250   }
4251
4252   if (agent->force_relay && !is_turn) {
4253     /* Ignore messages not from TURN if TURN is required */
4254     retval = RECV_WOULD_BLOCK;  /* EWOULDBLOCK */
4255     goto done;
4256   }
4257
4258   if (retval == RECV_OOB)
4259     goto done;
4260
4261   /* If the message’s stated length is equal to its actual length, it’s probably
4262    * a STUN message; otherwise it’s probably data. */
4263   if (stun_message_validate_buffer_length_fast (
4264       (StunInputVector *) message->buffers, message->n_buffers, message->length,
4265       (agent->compatibility != NICE_COMPATIBILITY_OC2007 &&
4266        agent->compatibility != NICE_COMPATIBILITY_OC2007R2)) == (ssize_t) message->length) {
4267     /* Slow path: If this message isn’t obviously *not* a STUN packet, compact
4268      * its buffers
4269      * into a single monolithic one and parse the packet properly. */
4270     guint8 *big_buf;
4271     gsize big_buf_len;
4272     int validated_len;
4273
4274     big_buf = compact_input_message (message, &big_buf_len);
4275
4276     validated_len = stun_message_validate_buffer_length (big_buf, big_buf_len,
4277         (agent->compatibility != NICE_COMPATIBILITY_OC2007 &&
4278          agent->compatibility != NICE_COMPATIBILITY_OC2007R2));
4279
4280     if (validated_len == (gint) big_buf_len) {
4281       gboolean handled;
4282
4283       handled =
4284         conn_check_handle_inbound_stun (agent, stream, component, nicesock,
4285             message->from, (gchar *) big_buf, big_buf_len);
4286
4287       if (handled) {
4288         /* Handled STUN message. */
4289         nice_debug ("%s: Valid STUN packet received.", G_STRFUNC);
4290         retval = RECV_OOB;
4291         g_free (big_buf);
4292         agent->media_after_tick = TRUE;
4293         goto done;
4294       }
4295     }
4296
4297     nice_debug ("%s: Packet passed fast STUN validation but failed "
4298         "slow validation.", G_STRFUNC);
4299
4300     g_free (big_buf);
4301   }
4302
4303   if (!nice_component_verify_remote_candidate (component,
4304       message->from, nicesock)) {
4305     if (nice_debug_is_verbose ()) {
4306       gchar str[INET6_ADDRSTRLEN];
4307
4308       nice_address_to_string (message->from, str);
4309       nice_debug_verbose ("Agent %p : %d:%d DROPPING packet from unknown source"
4310           " %s:%d sock-type: %d", agent, stream->id, component->id, str,
4311           nice_address_get_port (message->from), nicesock->type);
4312     }
4313
4314     retval = RECV_OOB;
4315     goto done;
4316   }
4317
4318   agent->media_after_tick = TRUE;
4319
4320   /* Unhandled STUN; try handling TCP data, then pass to the client. */
4321   if (message->length > 0  && agent->reliable) {
4322     if (!nice_socket_is_reliable (nicesock) &&
4323         !pseudo_tcp_socket_is_closed (component->tcp)) {
4324       /* If we don’t yet have an underlying selected socket, queue up the
4325        * incoming data to handle later. This is because we can’t send ACKs (or,
4326        * more importantly for the first few packets, SYNACKs) without an
4327        * underlying socket. We’d rather wait a little longer for a pair to be
4328        * selected, then process the incoming packets and send out ACKs, than try
4329        * to process them now, fail to send the ACKs, and incur a timeout in our
4330        * pseudo-TCP state machine. */
4331       if (component->selected_pair.local == NULL) {
4332         GOutputVector *vec = g_slice_new (GOutputVector);
4333         vec->buffer = compact_input_message (message, &vec->size);
4334         g_queue_push_tail (&component->queued_tcp_packets, vec);
4335         nice_debug ("%s: Queued %" G_GSSIZE_FORMAT " bytes for agent %p.",
4336             G_STRFUNC, vec->size, agent);
4337
4338         return RECV_OOB;
4339       } else {
4340         process_queued_tcp_packets (agent, stream, component);
4341       }
4342
4343       /* Received data on a reliable connection. */
4344
4345       nice_debug_verbose ("%s: notifying pseudo-TCP of packet, length %" G_GSIZE_FORMAT,
4346           G_STRFUNC, message->length);
4347       pseudo_tcp_socket_notify_message (component->tcp, message);
4348
4349       adjust_tcp_clock (agent, stream, component);
4350
4351       /* Success! Handled out-of-band. */
4352       retval = RECV_OOB;
4353       goto done;
4354     } else if (pseudo_tcp_socket_is_closed (component->tcp)) {
4355       nice_debug ("Received data on a pseudo tcp FAILED component. Ignoring.");
4356
4357       retval = RECV_OOB;
4358       goto done;
4359     }
4360   }
4361
4362 done:
4363   /* Clear local modifications. */
4364   if (message->from == &from) {
4365     message->from = NULL;
4366   }
4367
4368   return retval;
4369 }
4370
4371 /* Print the composition of an array of messages. No-op if debugging is
4372  * disabled. */
4373 static void
4374 nice_debug_input_message_composition (const NiceInputMessage *messages,
4375     guint n_messages)
4376 {
4377   guint i;
4378
4379   if (!nice_debug_is_verbose ())
4380     return;
4381
4382   for (i = 0; i < n_messages; i++) {
4383     const NiceInputMessage *message = &messages[i];
4384     guint j;
4385
4386     nice_debug_verbose ("Message %p (from: %p, length: %" G_GSIZE_FORMAT ")", message,
4387         message->from, message->length);
4388
4389     for (j = 0;
4390          (message->n_buffers >= 0 && j < (guint) message->n_buffers) ||
4391          (message->n_buffers < 0 && message->buffers[j].buffer != NULL);
4392          j++) {
4393       GInputVector *buffer = &message->buffers[j];
4394
4395       nice_debug_verbose ("\tBuffer %p (length: %" G_GSIZE_FORMAT ")", buffer->buffer,
4396           buffer->size);
4397     }
4398   }
4399 }
4400
4401 static guint8 *
4402 compact_message (const NiceOutputMessage *message, gsize buffer_length)
4403 {
4404   guint8 *buffer;
4405   gsize offset = 0;
4406   guint i;
4407
4408   buffer = g_malloc (buffer_length);
4409
4410   for (i = 0;
4411        (message->n_buffers >= 0 && i < (guint) message->n_buffers) ||
4412        (message->n_buffers < 0 && message->buffers[i].buffer != NULL);
4413        i++) {
4414     gsize len = MIN (buffer_length - offset, message->buffers[i].size);
4415     memcpy (buffer + offset, message->buffers[i].buffer, len);
4416     offset += len;
4417   }
4418
4419   return buffer;
4420 }
4421
4422 /* Concatenate all the buffers in the given @recv_message into a single, newly
4423  * allocated, monolithic buffer which is returned. The length of the new buffer
4424  * is returned in @buffer_length, and should be equal to the length field of
4425  * @recv_message.
4426  *
4427  * The return value must be freed with g_free(). */
4428 guint8 *
4429 compact_input_message (const NiceInputMessage *message, gsize *buffer_length)
4430 {
4431   nice_debug_verbose ("%s: **WARNING: SLOW PATH**", G_STRFUNC);
4432   nice_debug_input_message_composition (message, 1);
4433
4434   /* This works as long as NiceInputMessage is a subset of eNiceOutputMessage */
4435
4436   *buffer_length = message->length;
4437
4438   return compact_message ((NiceOutputMessage *) message, *buffer_length);
4439 }
4440
4441 /* Returns the number of bytes copied. Silently drops any data from @buffer
4442  * which doesn’t fit in @message. */
4443 gsize
4444 memcpy_buffer_to_input_message (NiceInputMessage *message,
4445     const guint8 *buffer, gsize buffer_length)
4446 {
4447   guint i;
4448
4449   nice_debug_verbose ("%s: **WARNING: SLOW PATH**", G_STRFUNC);
4450
4451   message->length = 0;
4452
4453   for (i = 0;
4454        buffer_length > 0 &&
4455        ((message->n_buffers >= 0 && i < (guint) message->n_buffers) ||
4456         (message->n_buffers < 0 && message->buffers[i].buffer != NULL));
4457        i++) {
4458     gsize len;
4459
4460     len = MIN (message->buffers[i].size, buffer_length);
4461     memcpy (message->buffers[i].buffer, buffer, len);
4462
4463     buffer += len;
4464     buffer_length -= len;
4465
4466     message->length += len;
4467   }
4468
4469   nice_debug_input_message_composition (message, 1);
4470
4471   if (buffer_length > 0) {
4472     g_warning ("Dropped %" G_GSIZE_FORMAT " bytes of data from the end of "
4473         "buffer %p (length: %" G_GSIZE_FORMAT ") due to not fitting in "
4474         "message %p", buffer_length, buffer - message->length,
4475         message->length + buffer_length, message);
4476   }
4477
4478   return message->length;
4479 }
4480
4481 /* Concatenate all the buffers in the given @message into a single, newly
4482  * allocated, monolithic buffer which is returned. The length of the new buffer
4483  * is returned in @buffer_length, and should be equal to the length field of
4484  * @recv_message.
4485  *
4486  * The return value must be freed with g_free(). */
4487 guint8 *
4488 compact_output_message (const NiceOutputMessage *message, gsize *buffer_length)
4489 {
4490   nice_debug ("%s: **WARNING: SLOW PATH**", G_STRFUNC);
4491
4492   *buffer_length = output_message_get_size (message);
4493
4494   return compact_message (message, *buffer_length);
4495 }
4496
4497 gsize
4498 output_message_get_size (const NiceOutputMessage *message)
4499 {
4500   guint i;
4501   gsize message_len = 0;
4502
4503   /* Find the total size of the message */
4504   for (i = 0;
4505        (message->n_buffers >= 0 && i < (guint) message->n_buffers) ||
4506            (message->n_buffers < 0 && message->buffers[i].buffer != NULL);
4507        i++)
4508     message_len += message->buffers[i].size;
4509
4510   return message_len;
4511 }
4512
4513 gsize
4514 input_message_get_size (const NiceInputMessage *message)
4515 {
4516   guint i;
4517   gsize message_len = 0;
4518
4519   /* Find the total size of the message */
4520   for (i = 0;
4521        (message->n_buffers >= 0 && i < (guint) message->n_buffers) ||
4522            (message->n_buffers < 0 && message->buffers[i].buffer != NULL);
4523        i++)
4524     message_len += message->buffers[i].size;
4525
4526   return message_len;
4527 }
4528
4529 /*
4530  * nice_input_message_iter_reset:
4531  * @iter: a #NiceInputMessageIter
4532  *
4533  * Reset the given @iter to point to the beginning of the array of messages.
4534  * This may be used both to initialise it and to reset it after use.
4535  *
4536  * Since: 0.1.5
4537  */
4538 void
4539 nice_input_message_iter_reset (NiceInputMessageIter *iter)
4540 {
4541   iter->message = 0;
4542   iter->buffer = 0;
4543   iter->offset = 0;
4544 }
4545
4546 /*
4547  * nice_input_message_iter_is_at_end:
4548  * @iter: a #NiceInputMessageIter
4549  * @messages: (array length=n_messages): an array of #NiceInputMessages
4550  * @n_messages: number of entries in @messages
4551  *
4552  * Determine whether @iter points to the end of the given @messages array. If it
4553  * does, the array is full: every buffer in every message is full of valid
4554  * bytes.
4555  *
4556  * Returns: %TRUE if the messages’ buffers are full, %FALSE otherwise
4557  *
4558  * Since: 0.1.5
4559  */
4560 gboolean
4561 nice_input_message_iter_is_at_end (NiceInputMessageIter *iter,
4562     NiceInputMessage *messages, guint n_messages)
4563 {
4564   return (iter->message == n_messages &&
4565       iter->buffer == 0 && iter->offset == 0);
4566 }
4567
4568 /*
4569  * nice_input_message_iter_get_n_valid_messages:
4570  * @iter: a #NiceInputMessageIter
4571  *
4572  * Calculate the number of valid messages in the messages array. A valid message
4573  * is one which contains at least one valid byte of data in its buffers.
4574  *
4575  * Returns: number of valid messages (may be zero)
4576  *
4577  * Since: 0.1.5
4578  */
4579 guint
4580 nice_input_message_iter_get_n_valid_messages (NiceInputMessageIter *iter)
4581 {
4582   if (iter->buffer == 0 && iter->offset == 0)
4583     return iter->message;
4584   else
4585     return iter->message + 1;
4586 }
4587
4588 /**
4589  * nice_input_message_iter_compare:
4590  * @a: a #NiceInputMessageIter
4591  * @b: another #NiceInputMessageIter
4592  *
4593  * Compare two #NiceInputMessageIters for equality, returning %TRUE if they
4594  * point to the same place in the receive message array.
4595  *
4596  * Returns: %TRUE if the iters match, %FALSE otherwise
4597  *
4598  * Since: 0.1.5
4599  */
4600 gboolean
4601 nice_input_message_iter_compare (const NiceInputMessageIter *a,
4602     const NiceInputMessageIter *b)
4603 {
4604   return (a->message == b->message && a->buffer == b->buffer && a->offset == b->offset);
4605 }
4606
4607 /* Will fill up @messages from the first free byte onwards (as determined using
4608  * @iter). This may be used in reliable or non-reliable mode; in non-reliable
4609  * mode it will always increment the message index after each buffer is
4610  * consumed.
4611  *
4612  * Updates @iter in place. No errors can occur.
4613  *
4614  * Returns the number of valid messages in @messages on success (which may be
4615  * zero if reading into the first buffer of the message would have blocked).
4616  *
4617  * Must be called with the io_mutex held. */
4618 static gint
4619 pending_io_messages_recv_messages (NiceComponent *component, gboolean reliable,
4620     NiceInputMessage *messages, guint n_messages, NiceInputMessageIter *iter)
4621 {
4622   gsize len;
4623   IOCallbackData *data;
4624   NiceInputMessage *message = &messages[iter->message];
4625
4626   g_assert_cmpuint (component->io_callback_id, ==, 0);
4627
4628   data = g_queue_peek_head (&component->pending_io_messages);
4629   if (data == NULL)
4630     goto done;
4631
4632   if (iter->buffer == 0 && iter->offset == 0) {
4633     message->length = 0;
4634   }
4635
4636   for (;
4637        (message->n_buffers >= 0 && iter->buffer < (guint) message->n_buffers) ||
4638        (message->n_buffers < 0 && message->buffers[iter->buffer].buffer != NULL);
4639        iter->buffer++) {
4640     GInputVector *buffer = &message->buffers[iter->buffer];
4641
4642     do {
4643       len = MIN (data->buf_len - data->offset, buffer->size - iter->offset);
4644       memcpy ((guint8 *) buffer->buffer + iter->offset,
4645           data->buf + data->offset, len);
4646
4647       nice_debug ("%s: Unbuffered %" G_GSIZE_FORMAT " bytes into "
4648           "buffer %p (offset %" G_GSIZE_FORMAT ", length %" G_GSIZE_FORMAT
4649           ").", G_STRFUNC, len, buffer->buffer, iter->offset, buffer->size);
4650
4651       message->length += len;
4652       iter->offset += len;
4653       data->offset += len;
4654     } while (iter->offset < buffer->size);
4655
4656     iter->offset = 0;
4657   }
4658
4659   /* Only if we managed to consume the whole buffer should it be popped off the
4660    * queue; otherwise we’ll have another go at it later. */
4661   if (data->offset == data->buf_len) {
4662     g_queue_pop_head (&component->pending_io_messages);
4663     io_callback_data_free (data);
4664
4665     /* If we’ve consumed an entire message from pending_io_messages, and
4666      * are in non-reliable mode, move on to the next message in
4667      * @messages. */
4668     if (!reliable) {
4669       iter->offset = 0;
4670       iter->buffer = 0;
4671       iter->message++;
4672     }
4673   }
4674
4675 done:
4676   return nice_input_message_iter_get_n_valid_messages (iter);
4677 }
4678
4679 static gboolean
4680 nice_agent_recv_cancelled_cb (GCancellable *cancellable, gpointer user_data)
4681 {
4682   GError **error = user_data;
4683
4684   if (error && !*error)
4685     g_cancellable_set_error_if_cancelled (cancellable, error);
4686   return G_SOURCE_REMOVE;
4687 }
4688
4689 static gint
4690 nice_agent_recv_messages_blocking_or_nonblocking (NiceAgent *agent,
4691   guint stream_id, guint component_id, gboolean blocking,
4692   NiceInputMessage *messages, guint n_messages,
4693   GCancellable *cancellable, GError **error)
4694 {
4695   GMainContext *context;
4696   NiceStream *stream;
4697   NiceComponent *component;
4698   gint n_valid_messages = -1;
4699   GSource *cancellable_source = NULL;
4700   gboolean received_enough = FALSE, error_reported = FALSE;
4701   gboolean all_sockets_would_block = FALSE;
4702   gboolean reached_eos = FALSE;
4703   GError *child_error = NULL;
4704   NiceInputMessage *messages_orig = NULL;
4705   guint i;
4706
4707   g_return_val_if_fail (NICE_IS_AGENT (agent), -1);
4708   g_return_val_if_fail (stream_id >= 1, -1);
4709   g_return_val_if_fail (component_id >= 1, -1);
4710   g_return_val_if_fail (n_messages == 0 || messages != NULL, -1);
4711   g_return_val_if_fail (
4712       cancellable == NULL || G_IS_CANCELLABLE (cancellable), -1);
4713   g_return_val_if_fail (error == NULL || *error == NULL, -1);
4714
4715   if (n_messages == 0)
4716     return 0;
4717
4718   if (n_messages > G_MAXINT) {
4719     g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
4720         "The number of messages can't exceed G_MAXINT: %d", G_MAXINT);
4721     return -1;
4722   }
4723
4724   /* Receive buffer size must be at least 1280 for STUN */
4725   if (!agent->reliable) {
4726     for (i = 0; i < n_messages; i++) {
4727       if (input_message_get_size (&messages[i]) < 1280) {
4728         GInputVector *vec;
4729
4730         if (messages_orig == NULL)
4731           messages_orig = g_memdup (messages,
4732               sizeof (NiceInputMessage) * n_messages);
4733         vec = g_slice_new (GInputVector);
4734         vec->buffer = g_slice_alloc (1280);
4735         vec->size = 1280;
4736         messages[i].buffers = vec;
4737         messages[i].n_buffers = 1;
4738       }
4739     }
4740   }
4741
4742   agent_lock (agent);
4743
4744   if (!agent_find_component (agent, stream_id, component_id,
4745           &stream, &component)) {
4746     g_set_error (&child_error, G_IO_ERROR, G_IO_ERROR_BROKEN_PIPE,
4747                  "Invalid stream/component.");
4748     goto done;
4749   }
4750
4751   nice_debug_verbose ("%s: %p: (%s):", G_STRFUNC, agent,
4752       blocking ? "blocking" : "non-blocking");
4753   nice_debug_input_message_composition (messages, n_messages);
4754
4755   /* Disallow re-entrant reads. */
4756   g_assert (component->n_recv_messages == 0 &&
4757       component->recv_messages == NULL);
4758
4759   /* Set the component’s receive buffer. */
4760   context = nice_component_dup_io_context (component);
4761   nice_component_set_io_callback (component, NULL, NULL, messages, n_messages,
4762       &child_error);
4763
4764   /* Add the cancellable as a source. */
4765   if (cancellable != NULL) {
4766     cancellable_source = g_cancellable_source_new (cancellable);
4767     g_source_set_callback (cancellable_source,
4768         (GSourceFunc) G_CALLBACK (nice_agent_recv_cancelled_cb), &child_error,
4769         NULL);
4770     g_source_attach (cancellable_source, context);
4771   }
4772
4773   /* Is there already pending data left over from having an I/O callback
4774    * attached and switching to using nice_agent_recv()? This is a horrifically
4775    * specific use case which I hope nobody ever tries. And yet, it still must be
4776    * supported. */
4777   g_mutex_lock (&component->io_mutex);
4778
4779   while (!received_enough &&
4780          !g_queue_is_empty (&component->pending_io_messages)) {
4781     pending_io_messages_recv_messages (component, agent->reliable,
4782         component->recv_messages, component->n_recv_messages,
4783         &component->recv_messages_iter);
4784
4785     nice_debug_verbose ("%s: %p: Received %d valid messages from pending I/O buffer.",
4786         G_STRFUNC, agent,
4787         nice_input_message_iter_get_n_valid_messages (
4788             &component->recv_messages_iter));
4789
4790     received_enough =
4791         nice_input_message_iter_is_at_end (&component->recv_messages_iter,
4792             component->recv_messages, component->n_recv_messages);
4793   }
4794
4795   g_mutex_unlock (&component->io_mutex);
4796
4797   /* For a reliable stream, grab any data from the pseudo-TCP input buffer
4798    * before trying the sockets. */
4799   if (agent->reliable &&
4800       pseudo_tcp_socket_get_available_bytes (component->tcp) > 0) {
4801     pseudo_tcp_socket_recv_messages (component->tcp,
4802         component->recv_messages, component->n_recv_messages,
4803         &component->recv_messages_iter, &child_error);
4804     adjust_tcp_clock (agent, stream, component);
4805
4806     nice_debug_verbose ("%s: %p: Received %d valid messages from pseudo-TCP read "
4807         "buffer.", G_STRFUNC, agent,
4808         nice_input_message_iter_get_n_valid_messages (
4809             &component->recv_messages_iter));
4810
4811     received_enough =
4812         nice_input_message_iter_is_at_end (&component->recv_messages_iter,
4813             component->recv_messages, component->n_recv_messages);
4814     error_reported = (child_error != NULL);
4815   }
4816
4817   /* Each iteration of the main context will either receive some data, a
4818    * cancellation error or a socket error. In non-reliable mode, the iter’s
4819    * @message counter will be incremented after each read.
4820    *
4821    * In blocking, reliable mode, iterate the loop enough to fill exactly
4822    * @n_messages messages. In blocking, non-reliable mode, iterate the loop to
4823    * receive @n_messages messages (which may not fill all the buffers). In
4824    * non-blocking mode, stop iterating the loop if all sockets would block (i.e.
4825    * if no data was received for an iteration; in which case @child_error will
4826    * be set to %G_IO_ERROR_WOULD_BLOCK).
4827    */
4828   while (!received_enough && !error_reported && !all_sockets_would_block &&
4829       !reached_eos) {
4830     NiceInputMessageIter prev_recv_messages_iter;
4831
4832     g_clear_error (&child_error);
4833     memcpy (&prev_recv_messages_iter, &component->recv_messages_iter,
4834         sizeof (NiceInputMessageIter));
4835
4836     agent_unlock (agent);
4837     g_main_context_iteration (context, blocking);
4838     agent_lock (agent);
4839
4840     if (!agent_find_component (agent, stream_id, component_id,
4841             &stream, &component)) {
4842       g_clear_error (&child_error);
4843       g_set_error (&child_error, G_IO_ERROR, G_IO_ERROR_BROKEN_PIPE,
4844           "Component removed during call.");
4845
4846       component = NULL;
4847
4848       goto recv_error;
4849     }
4850
4851     received_enough =
4852         nice_input_message_iter_is_at_end (&component->recv_messages_iter,
4853             component->recv_messages, component->n_recv_messages);
4854     error_reported = (child_error != NULL &&
4855         !g_error_matches (child_error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK));
4856     reached_eos = (agent->reliable &&
4857         pseudo_tcp_socket_is_closed_remotely (component->tcp) &&
4858         nice_input_message_iter_compare (&prev_recv_messages_iter,
4859             &component->recv_messages_iter));
4860     all_sockets_would_block = (!blocking && !reached_eos &&
4861         nice_input_message_iter_compare (&prev_recv_messages_iter,
4862             &component->recv_messages_iter));
4863   }
4864
4865   n_valid_messages =
4866       nice_input_message_iter_get_n_valid_messages (
4867           &component->recv_messages_iter);  /* grab before resetting the iter */
4868
4869   nice_component_set_io_callback (component, NULL, NULL, NULL, 0, NULL);
4870
4871 recv_error:
4872   /* Tidy up. Below this point, @component may be %NULL. */
4873   if (cancellable_source != NULL) {
4874     g_source_destroy (cancellable_source);
4875     g_source_unref (cancellable_source);
4876   }
4877
4878   g_main_context_unref (context);
4879
4880   /* Handle errors and cancellations. */
4881   if (child_error != NULL) {
4882     n_valid_messages = -1;
4883   } else if (n_valid_messages == 0 && all_sockets_would_block) {
4884     g_set_error_literal (&child_error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
4885         g_strerror (EAGAIN));
4886     n_valid_messages = -1;
4887   }
4888
4889   nice_debug_verbose ("%s: %p: n_valid_messages: %d, n_messages: %u", G_STRFUNC, agent,
4890       n_valid_messages, n_messages);
4891
4892 done:
4893   g_assert ((child_error != NULL) == (n_valid_messages == -1));
4894   g_assert (n_valid_messages < 0 || (guint) n_valid_messages <= n_messages);
4895   g_assert (n_valid_messages != 0 || reached_eos);
4896
4897   if (child_error != NULL)
4898     g_propagate_error (error, child_error);
4899
4900   agent_unlock_and_emit (agent);
4901
4902   if (messages_orig) {
4903     for (i = 0; i < n_messages; i++) {
4904       if (messages[i].buffers != messages_orig[i].buffers) {
4905         g_assert_cmpint (messages[i].n_buffers, ==, 1);
4906
4907         memcpy_buffer_to_input_message (&messages_orig[i],
4908             messages[i].buffers[0].buffer, messages[i].length);
4909
4910         g_slice_free1 (1280, messages[i].buffers[0].buffer);
4911         g_slice_free (GInputVector, messages[i].buffers);
4912
4913         messages[i].buffers = messages_orig[i].buffers;
4914         messages[i].n_buffers = messages_orig[i].n_buffers;
4915         messages[i].length = messages_orig[i].length;
4916       }
4917     }
4918     g_free (messages_orig);
4919   }
4920
4921   return n_valid_messages;
4922 }
4923
4924 NICEAPI_EXPORT gint
4925 nice_agent_recv_messages (NiceAgent *agent, guint stream_id, guint component_id,
4926   NiceInputMessage *messages, guint n_messages, GCancellable *cancellable,
4927   GError **error)
4928 {
4929   return nice_agent_recv_messages_blocking_or_nonblocking (agent, stream_id,
4930       component_id, TRUE, messages, n_messages, cancellable, error);
4931 }
4932
4933 NICEAPI_EXPORT gssize
4934 nice_agent_recv (NiceAgent *agent, guint stream_id, guint component_id,
4935   guint8 *buf, gsize buf_len, GCancellable *cancellable, GError **error)
4936 {
4937   gint n_valid_messages;
4938   GInputVector local_bufs = { buf, buf_len };
4939   NiceInputMessage local_messages = { &local_bufs, 1, NULL, 0 };
4940
4941   g_return_val_if_fail (NICE_IS_AGENT (agent), -1);
4942   g_return_val_if_fail (stream_id >= 1, -1);
4943   g_return_val_if_fail (component_id >= 1, -1);
4944   g_return_val_if_fail (buf != NULL || buf_len == 0, -1);
4945   g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), -1);
4946   g_return_val_if_fail (error == NULL || *error == NULL, -1);
4947
4948   if (buf_len > G_MAXSSIZE) {
4949     g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
4950         "The buffer length can't exceed G_MAXSSIZE: %" G_GSSIZE_FORMAT,
4951         G_MAXSSIZE);
4952     return -1;
4953   }
4954
4955   n_valid_messages = nice_agent_recv_messages (agent, stream_id, component_id,
4956       &local_messages, 1, cancellable, error);
4957
4958   if (n_valid_messages <= 0)
4959     return n_valid_messages;
4960
4961   return local_messages.length;
4962 }
4963
4964 NICEAPI_EXPORT gint
4965 nice_agent_recv_messages_nonblocking (NiceAgent *agent, guint stream_id,
4966     guint component_id, NiceInputMessage *messages, guint n_messages,
4967     GCancellable *cancellable, GError **error)
4968 {
4969   return nice_agent_recv_messages_blocking_or_nonblocking (agent, stream_id,
4970       component_id, FALSE, messages, n_messages, cancellable, error);
4971 }
4972
4973 NICEAPI_EXPORT gssize
4974 nice_agent_recv_nonblocking (NiceAgent *agent, guint stream_id,
4975     guint component_id, guint8 *buf, gsize buf_len, GCancellable *cancellable,
4976     GError **error)
4977 {
4978   gint n_valid_messages;
4979   GInputVector local_bufs = { buf, buf_len };
4980   NiceInputMessage local_messages = { &local_bufs, 1, NULL, 0 };
4981
4982   g_return_val_if_fail (NICE_IS_AGENT (agent), -1);
4983   g_return_val_if_fail (stream_id >= 1, -1);
4984   g_return_val_if_fail (component_id >= 1, -1);
4985   g_return_val_if_fail (buf != NULL || buf_len == 0, -1);
4986   g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), -1);
4987   g_return_val_if_fail (error == NULL || *error == NULL, -1);
4988
4989   if (buf_len > G_MAXSSIZE) {
4990     g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
4991         "The buffer length can't exceed G_MAXSSIZE: %" G_GSSIZE_FORMAT,
4992         G_MAXSSIZE);
4993     return -1;
4994   }
4995
4996   n_valid_messages = nice_agent_recv_messages_nonblocking (agent, stream_id,
4997       component_id, &local_messages, 1, cancellable, error);
4998
4999   if (n_valid_messages <= 0)
5000     return n_valid_messages;
5001
5002   return local_messages.length;
5003 }
5004
5005 /* nice_agent_send_messages_nonblocking_internal:
5006  *
5007  * Returns: number of bytes sent if allow_partial is %TRUE, the number
5008  * of messages otherwise.
5009  */
5010
5011 static gint
5012 nice_agent_send_messages_nonblocking_internal (
5013   NiceAgent *agent,
5014   guint stream_id,
5015   guint component_id,
5016   const NiceOutputMessage *messages,
5017   guint n_messages,
5018   gboolean allow_partial,
5019   GError **error)
5020 {
5021   NiceStream *stream;
5022   NiceComponent *component;
5023   gint n_sent = -1; /* is in bytes if allow_partial is TRUE,
5024                        otherwise in messages */
5025   GError *child_error = NULL;
5026
5027   g_assert (n_messages == 1 || !allow_partial);
5028
5029   agent_lock (agent);
5030
5031   if (!agent_find_component (agent, stream_id, component_id,
5032           &stream, &component)) {
5033     g_set_error (&child_error, G_IO_ERROR, G_IO_ERROR_BROKEN_PIPE,
5034                  "Invalid stream/component.");
5035     goto done;
5036   }
5037
5038   /* FIXME: Cancellation isn’t yet supported, but it doesn’t matter because
5039    * we only deal with non-blocking writes. */
5040   if (component->selected_pair.local != NULL) {
5041     if (nice_debug_is_enabled ()) {
5042       gchar tmpbuf[INET6_ADDRSTRLEN];
5043       nice_address_to_string (&component->selected_pair.remote->addr, tmpbuf);
5044
5045       nice_debug_verbose ("Agent %p : s%d:%d: sending %u messages to "
5046           "[%s]:%d", agent, stream_id, component_id, n_messages, tmpbuf,
5047           nice_address_get_port (&component->selected_pair.remote->addr));
5048     }
5049
5050     if(agent->reliable &&
5051         !nice_socket_is_reliable (component->selected_pair.local->sockptr)) {
5052       if (!pseudo_tcp_socket_is_closed (component->tcp)) {
5053         /* Send on the pseudo-TCP socket. */
5054         n_sent = pseudo_tcp_socket_send_messages (component->tcp, messages,
5055             n_messages, allow_partial, &child_error);
5056         adjust_tcp_clock (agent, stream, component);
5057
5058         if (!pseudo_tcp_socket_can_send (component->tcp))
5059           g_cancellable_reset (component->tcp_writable_cancellable);
5060         if (n_sent < 0 && !g_error_matches (child_error, G_IO_ERROR,
5061                 G_IO_ERROR_WOULD_BLOCK)) {
5062           /* Signal errors */
5063           priv_pseudo_tcp_error (agent, component);
5064         }
5065       } else {
5066         g_set_error (&child_error, G_IO_ERROR, G_IO_ERROR_FAILED,
5067             "Pseudo-TCP socket not connected.");
5068       }
5069     } else {
5070       NiceSocket *sock;
5071       NiceAddress *addr;
5072
5073       sock = component->selected_pair.local->sockptr;
5074       addr = &component->selected_pair.remote->addr;
5075
5076       if (nice_socket_is_reliable (sock)) {
5077         guint i;
5078
5079         /* ICE-TCP requires that all packets be framed with RFC4571 */
5080         n_sent = 0;
5081         for (i = 0; i < n_messages; i++) {
5082           const NiceOutputMessage *message = &messages[i];
5083           gsize message_len = output_message_get_size (message);
5084           gsize offset = 0;
5085           gsize current_offset = 0;
5086           gsize offset_in_buffer = 0;
5087           gint n_sent_framed;
5088           GOutputVector *local_bufs;
5089           NiceOutputMessage local_message;
5090           guint j;
5091           guint n_bufs = 0;
5092
5093           /* Count the number of buffers. */
5094           if (message->n_buffers == -1) {
5095             for (j = 0; message->buffers[j].buffer != NULL; j++)
5096               n_bufs++;
5097           } else {
5098             n_bufs = message->n_buffers;
5099           }
5100
5101           local_bufs = g_malloc_n (n_bufs + 1, sizeof (GOutputVector));
5102           local_message.buffers = local_bufs;
5103
5104           while (message_len > 0) {
5105             guint16 packet_len;
5106             guint16 rfc4571_frame;
5107
5108             /* Split long messages into 62KB packets, leaving enough space
5109              * for TURN overhead as well */
5110             if (message_len > 0xF800)
5111               packet_len = 0xF800;
5112             else
5113               packet_len = (guint16) message_len;
5114             message_len -= packet_len;
5115             rfc4571_frame = htons (packet_len);
5116
5117             local_bufs[0].buffer = &rfc4571_frame;
5118             local_bufs[0].size = sizeof (guint16);
5119
5120             local_message.n_buffers = 1;
5121             /* If we had to split the message, we need to find which buffer
5122              * to start copying from and our offset within that buffer */
5123             offset_in_buffer = 0;
5124             current_offset = 0;
5125             for (j = 0; j < n_bufs; j++) {
5126               if (message->buffers[j].size < offset - current_offset) {
5127                 current_offset += message->buffers[j].size;
5128                 continue;
5129               } else {
5130                 offset_in_buffer = offset - current_offset;
5131                 current_offset = offset;
5132                 break;
5133               }
5134             }
5135
5136             /* Keep j position in array and start copying from there */
5137             for (; j < n_bufs; j++) {
5138               local_bufs[local_message.n_buffers].buffer =
5139                   ((guint8 *) message->buffers[j].buffer) + offset_in_buffer;
5140               local_bufs[local_message.n_buffers].size =
5141                   MIN (message->buffers[j].size, packet_len);
5142               packet_len -= local_bufs[local_message.n_buffers].size;
5143               offset += local_bufs[local_message.n_buffers++].size;
5144               offset_in_buffer = 0;
5145             }
5146
5147             /* If we sent part of the message already, then send the rest
5148              * reliably so the message is sent as a whole even if it's split */
5149             if (current_offset == 0)
5150               n_sent_framed = nice_socket_send_messages (sock, addr,
5151                   &local_message, 1);
5152             else
5153               n_sent_framed = nice_socket_send_messages_reliable (sock, addr,
5154                   &local_message, 1);
5155
5156             if (component->tcp_writable_cancellable &&
5157                 !nice_socket_can_send (sock, addr))
5158               g_cancellable_reset (component->tcp_writable_cancellable);
5159
5160             if (n_sent_framed < 0 && n_sent == 0)
5161               n_sent = n_sent_framed;
5162             if (n_sent_framed != 1)
5163               break;
5164             /* This is the last split frame, increment n_sent */
5165             if (message_len == 0)
5166               n_sent ++;
5167           }
5168           g_free (local_bufs);
5169         }
5170
5171       } else {
5172         n_sent = nice_socket_send_messages (sock, addr, messages, n_messages);
5173       }
5174
5175       if (n_sent < 0) {
5176         g_set_error (&child_error, G_IO_ERROR, G_IO_ERROR_FAILED,
5177             "Error writing data to socket.");
5178       } else if (n_sent > 0 && allow_partial) {
5179         g_assert_cmpuint (n_messages, ==, 1);
5180         n_sent = output_message_get_size (messages);
5181       }
5182     }
5183   } else {
5184     /* Socket isn’t properly open yet. */
5185     n_sent = 0;  /* EWOULDBLOCK */
5186   }
5187
5188   /* Handle errors and cancellations. */
5189   if (n_sent == 0) {
5190     g_set_error_literal (&child_error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
5191         g_strerror (EAGAIN));
5192     n_sent = -1;
5193   }
5194
5195   nice_debug_verbose ("%s: n_sent: %d, n_messages: %u", G_STRFUNC,
5196       n_sent, n_messages);
5197
5198 done:
5199   g_assert ((child_error != NULL) == (n_sent == -1));
5200   g_assert_cmpint (n_sent, !=, 0);
5201   g_assert (n_sent < 0 ||
5202       (!allow_partial && (guint) n_sent <= n_messages) ||
5203       (allow_partial && n_messages == 1 &&
5204           (gsize) n_sent <= output_message_get_size (&messages[0])));
5205
5206   if (child_error != NULL)
5207     g_propagate_error (error, child_error);
5208
5209   agent_unlock_and_emit (agent);
5210
5211   return n_sent;
5212 }
5213
5214 NICEAPI_EXPORT gint
5215 nice_agent_send_messages_nonblocking (
5216   NiceAgent *agent,
5217   guint stream_id,
5218   guint component_id,
5219   const NiceOutputMessage *messages,
5220   guint n_messages,
5221   GCancellable *cancellable,
5222   GError **error)
5223 {
5224   g_return_val_if_fail (NICE_IS_AGENT (agent), -1);
5225   g_return_val_if_fail (stream_id >= 1, -1);
5226   g_return_val_if_fail (component_id >= 1, -1);
5227   g_return_val_if_fail (n_messages == 0 || messages != NULL, -1);
5228   g_return_val_if_fail (
5229       cancellable == NULL || G_IS_CANCELLABLE (cancellable), -1);
5230   g_return_val_if_fail (error == NULL || *error == NULL, -1);
5231
5232   if (g_cancellable_set_error_if_cancelled (cancellable, error))
5233     return -1;
5234
5235   return nice_agent_send_messages_nonblocking_internal (agent, stream_id,
5236       component_id, messages, n_messages, FALSE, error);
5237 }
5238
5239 NICEAPI_EXPORT gint
5240 nice_agent_send (
5241   NiceAgent *agent,
5242   guint stream_id,
5243   guint component_id,
5244   guint len,
5245   const gchar *buf)
5246 {
5247   GOutputVector local_buf = { buf, len };
5248   NiceOutputMessage local_message = { &local_buf, 1 };
5249   gint n_sent_bytes;
5250
5251   g_return_val_if_fail (NICE_IS_AGENT (agent), -1);
5252   g_return_val_if_fail (stream_id >= 1, -1);
5253   g_return_val_if_fail (component_id >= 1, -1);
5254   g_return_val_if_fail (buf != NULL, -1);
5255
5256   n_sent_bytes = nice_agent_send_messages_nonblocking_internal (agent,
5257       stream_id, component_id, &local_message, 1, TRUE, NULL);
5258
5259   return n_sent_bytes;
5260 }
5261
5262 NICEAPI_EXPORT GSList *
5263 nice_agent_get_local_candidates (
5264   NiceAgent *agent,
5265   guint stream_id,
5266   guint component_id)
5267 {
5268   NiceComponent *component;
5269   GSList * ret = NULL;
5270   GSList * item = NULL;
5271
5272   g_return_val_if_fail (NICE_IS_AGENT (agent), NULL);
5273   g_return_val_if_fail (stream_id >= 1, NULL);
5274   g_return_val_if_fail (component_id >= 1, NULL);
5275
5276   agent_lock (agent);
5277
5278   if (!agent_find_component (agent, stream_id, component_id, NULL, &component)) {
5279     goto done;
5280   }
5281
5282   for (item = component->local_candidates; item; item = item->next) {
5283     NiceCandidate *cand = item->data;
5284
5285     if (agent->force_relay && cand->type != NICE_CANDIDATE_TYPE_RELAYED)
5286       continue;
5287
5288     ret = g_slist_append (ret, nice_candidate_copy (cand));
5289   }
5290
5291  done:
5292   agent_unlock_and_emit (agent);
5293   return ret;
5294 }
5295
5296
5297 NICEAPI_EXPORT GSList *
5298 nice_agent_get_remote_candidates (
5299   NiceAgent *agent,
5300   guint stream_id,
5301   guint component_id)
5302 {
5303   NiceComponent *component;
5304   GSList *ret = NULL, *item = NULL;
5305
5306   g_return_val_if_fail (NICE_IS_AGENT (agent), NULL);
5307   g_return_val_if_fail (stream_id >= 1, NULL);
5308   g_return_val_if_fail (component_id >= 1, NULL);
5309
5310   agent_lock (agent);
5311   if (!agent_find_component (agent, stream_id, component_id, NULL, &component))
5312     {
5313       goto done;
5314     }
5315
5316   for (item = component->remote_candidates; item; item = item->next)
5317     ret = g_slist_append (ret, nice_candidate_copy (item->data));
5318
5319  done:
5320   agent_unlock_and_emit (agent);
5321   return ret;
5322 }
5323
5324 gboolean
5325 nice_agent_restart (
5326   NiceAgent *agent)
5327 {
5328   GSList *i;
5329
5330   agent_lock (agent);
5331
5332   /* step: regenerate tie-breaker value */
5333   priv_generate_tie_breaker (agent);
5334
5335   /* step: reset controlling mode from the property value */
5336   agent->controlling_mode = agent->saved_controlling_mode;
5337   nice_debug ("Agent %p : ICE restart, reset role to \"%s\".",
5338       agent, agent->controlling_mode ? "controlling" : "controlled");
5339
5340   for (i = agent->streams; i; i = i->next) {
5341     NiceStream *stream = i->data;
5342
5343     /* step: reset local credentials for the stream and
5344      * clean up the list of remote candidates */
5345     nice_stream_restart (stream, agent);
5346   }
5347
5348   agent_unlock_and_emit (agent);
5349   return TRUE;
5350 }
5351
5352 gboolean
5353 nice_agent_restart_stream (
5354     NiceAgent *agent,
5355     guint stream_id)
5356 {
5357   gboolean res = FALSE;
5358   NiceStream *stream;
5359
5360   agent_lock (agent);
5361
5362   stream = agent_find_stream (agent, stream_id);
5363   if (!stream) {
5364     g_warning ("Could not find  stream %u", stream_id);
5365     goto done;
5366   }
5367
5368   /* step: reset local credentials for the stream and
5369    * clean up the list of remote candidates */
5370   nice_stream_restart (stream, agent);
5371
5372   res = TRUE;
5373  done:
5374   agent_unlock_and_emit (agent);
5375   return res;
5376 }
5377
5378
5379 static void
5380 nice_agent_dispose (GObject *object)
5381 {
5382   GSList *i;
5383   QueuedSignal *sig;
5384   NiceAgent *agent = NICE_AGENT (object);
5385
5386   agent_lock (agent);
5387
5388   /* step: free resources for the binding discovery timers */
5389   discovery_free (agent);
5390   g_assert (agent->discovery_list == NULL);
5391
5392   /* step: free resources for the connectivity check timers */
5393   conn_check_free (agent);
5394
5395   priv_remove_keepalive_timer (agent);
5396
5397   for (i = agent->local_addresses; i; i = i->next)
5398     {
5399       NiceAddress *a = i->data;
5400
5401       nice_address_free (a);
5402     }
5403
5404   g_slist_free (agent->local_addresses);
5405   agent->local_addresses = NULL;
5406
5407   while (agent->streams) {
5408     NiceStream *s = agent->streams->data;
5409
5410     nice_stream_close (agent, s);
5411     g_object_unref (s);
5412
5413     agent->streams = g_slist_delete_link(agent->streams, agent->streams);
5414   }
5415
5416   while (agent->pruning_streams) {
5417     NiceStream *s = agent->pruning_streams->data;
5418
5419     nice_stream_close (agent, s);
5420     g_object_unref (s);
5421
5422     agent->pruning_streams = g_slist_delete_link(agent->pruning_streams,
5423         agent->pruning_streams);
5424   }
5425
5426   while ((sig = g_queue_pop_head (&agent->pending_signals))) {
5427     free_queued_signal (sig);
5428   }
5429
5430   g_free (agent->stun_server_ip);
5431   agent->stun_server_ip = NULL;
5432
5433   g_free (agent->proxy_ip);
5434   agent->proxy_ip = NULL;
5435   g_free (agent->proxy_username);
5436   agent->proxy_username = NULL;
5437   g_free (agent->proxy_password);
5438   agent->proxy_password = NULL;
5439
5440   nice_rng_free (agent->rng);
5441   agent->rng = NULL;
5442
5443   priv_stop_upnp (agent);
5444
5445 #ifdef HAVE_GUPNP
5446   if (agent->upnp) {
5447     g_object_unref (agent->upnp);
5448     agent->upnp = NULL;
5449   }
5450 #endif
5451
5452   g_free (agent->software_attribute);
5453   agent->software_attribute = NULL;
5454
5455   if (agent->main_context != NULL)
5456     g_main_context_unref (agent->main_context);
5457   agent->main_context = NULL;
5458
5459   agent_unlock (agent);
5460
5461   g_mutex_clear (&agent->agent_mutex);
5462
5463   if (G_OBJECT_CLASS (nice_agent_parent_class)->dispose)
5464     G_OBJECT_CLASS (nice_agent_parent_class)->dispose (object);
5465
5466 }
5467
5468 gboolean
5469 component_io_cb (GSocket *gsocket, GIOCondition condition, gpointer user_data)
5470 {
5471   SocketSource *socket_source = user_data;
5472   NiceComponent *component;
5473   NiceAgent *agent;
5474   NiceStream *stream;
5475   gboolean has_io_callback;
5476   gboolean remove_source = FALSE;
5477
5478   component = socket_source->component;
5479
5480   agent = g_weak_ref_get (&component->agent_ref);
5481   if (agent == NULL)
5482     return G_SOURCE_REMOVE;
5483
5484   agent_lock (agent);
5485
5486   stream = agent_find_stream (agent, component->stream_id);
5487
5488   if (stream == NULL) {
5489     nice_debug ("%s: stream %d destroyed", G_STRFUNC, component->stream_id);
5490
5491     agent_unlock (agent);
5492     g_object_unref (agent);
5493     return G_SOURCE_REMOVE;
5494   }
5495
5496   if (g_source_is_destroyed (g_main_current_source ())) {
5497     /* Silently return FALSE. */
5498     nice_debug ("%s: source %p destroyed", G_STRFUNC, g_main_current_source ());
5499
5500     agent_unlock (agent);
5501     g_object_unref (agent);
5502     return G_SOURCE_REMOVE;
5503   }
5504
5505   /* Remove disconnected sockets when we get a HUP */
5506   if (condition & G_IO_HUP) {
5507     nice_debug ("Agent %p: NiceSocket %p has received HUP", agent,
5508         socket_source->socket);
5509     if (component->selected_pair.local &&
5510         component->selected_pair.local->sockptr == socket_source->socket &&
5511         component->state == NICE_COMPONENT_STATE_READY) {
5512       nice_debug ("Agent %p: Selected pair socket %p has HUP, declaring failed",
5513           agent, socket_source->socket);
5514       agent_signal_component_state_change (agent,
5515           stream->id, component->id, NICE_COMPONENT_STATE_FAILED);
5516     }
5517
5518     nice_component_remove_socket (agent, component, socket_source->socket);
5519     agent_unlock (agent);
5520     g_object_unref (agent);
5521     return G_SOURCE_REMOVE;
5522   }
5523
5524   has_io_callback = nice_component_has_io_callback (component);
5525
5526   /* Choose which receive buffer to use. If we’re reading for
5527    * nice_agent_attach_recv(), use a local static buffer. If we’re reading for
5528    * nice_agent_recv_messages(), use the buffer provided by the client.
5529    *
5530    * has_io_callback cannot change throughout this function, as we operate
5531    * entirely with the agent lock held, and nice_component_set_io_callback()
5532    * would need to take the agent lock to change the Component’s
5533    * io_callback. */
5534   g_assert (!has_io_callback || component->recv_messages == NULL);
5535
5536   if (agent->reliable && !nice_socket_is_reliable (socket_source->socket)) {
5537 #define TCP_HEADER_SIZE 24 /* bytes */
5538     guint8 local_header_buf[TCP_HEADER_SIZE];
5539     /* FIXME: Currently, the critical path for reliable packet delivery has two
5540      * memcpy()s: one into the pseudo-TCP receive buffer, and one out of it.
5541      * This could moderately easily be reduced to one memcpy() in the common
5542      * case of in-order packet delivery, by replacing local_body_buf with a
5543      * pointer into the pseudo-TCP receive buffer. If it turns out the packet
5544      * is out-of-order (which we can only know after parsing its header), the
5545      * data will need to be moved in the buffer. If the packet *is* in order,
5546      * however, the only memcpy() then needed is from the pseudo-TCP receive
5547      * buffer to the client’s message buffers.
5548      *
5549      * In fact, in the case of a reliable agent with I/O callbacks, zero
5550      * memcpy()s can be achieved (for in-order packet delivery) by emittin the
5551      * I/O callback directly from the pseudo-TCP receive buffer. */
5552     guint8 local_body_buf[MAX_BUFFER_SIZE];
5553     GInputVector local_bufs[] = {
5554       { local_header_buf, sizeof (local_header_buf) },
5555       { local_body_buf, sizeof (local_body_buf) },
5556     };
5557     NiceInputMessage local_message = {
5558       local_bufs, G_N_ELEMENTS (local_bufs), NULL, 0
5559     };
5560     RecvStatus retval = 0;
5561
5562     if (pseudo_tcp_socket_is_closed (component->tcp)) {
5563       nice_debug ("Agent %p: not handling incoming packet for s%d:%d "
5564           "because pseudo-TCP socket does not exist in reliable mode.", agent,
5565           stream->id, component->id);
5566       remove_source = TRUE;
5567       goto done;
5568     }
5569
5570     while (has_io_callback ||
5571         (component->recv_messages != NULL &&
5572             !nice_input_message_iter_is_at_end (&component->recv_messages_iter,
5573                 component->recv_messages, component->n_recv_messages))) {
5574       /* Receive a single message. This will receive it into the given
5575        * @local_bufs then, for pseudo-TCP, emit I/O callbacks or copy it into
5576        * component->recv_messages in pseudo_tcp_socket_readable(). STUN packets
5577        * will be parsed in-place. */
5578       retval = agent_recv_message_unlocked (agent, stream, component,
5579           socket_source->socket, &local_message);
5580
5581       nice_debug_verbose ("%s: %p: received %d valid messages with %" G_GSSIZE_FORMAT
5582           " bytes", G_STRFUNC, agent, retval, local_message.length);
5583
5584       /* Don’t expect any valid messages to escape pseudo_tcp_socket_readable()
5585        * when in reliable mode. */
5586       g_assert_cmpint (retval, !=, RECV_SUCCESS);
5587
5588       if (retval == RECV_WOULD_BLOCK) {
5589         /* EWOULDBLOCK. */
5590         break;
5591       } else if (retval == RECV_ERROR) {
5592         /* Other error. */
5593         nice_debug ("%s: error receiving message", G_STRFUNC);
5594         remove_source = TRUE;
5595         break;
5596       }
5597
5598       has_io_callback = nice_component_has_io_callback (component);
5599     }
5600   } else if (has_io_callback) {
5601     while (has_io_callback) {
5602       guint8 local_buf[MAX_BUFFER_SIZE];
5603       GInputVector local_bufs = { local_buf, sizeof (local_buf) };
5604       NiceInputMessage local_message = { &local_bufs, 1, NULL, 0 };
5605       RecvStatus retval;
5606
5607       /* Receive a single message. */
5608       retval = agent_recv_message_unlocked (agent, stream, component,
5609           socket_source->socket, &local_message);
5610
5611       if (retval == RECV_WOULD_BLOCK) {
5612         /* EWOULDBLOCK. */
5613         nice_debug_verbose ("%s: %p: no message available on read attempt",
5614             G_STRFUNC, agent);
5615         break;
5616       } else if (retval == RECV_ERROR) {
5617         /* Other error. */
5618         nice_debug ("%s: %p: error receiving message", G_STRFUNC, agent);
5619         remove_source = TRUE;
5620         break;
5621       }
5622
5623       if (retval == RECV_SUCCESS) {
5624         nice_debug_verbose ("%s: %p: received a valid message with %" G_GSSIZE_FORMAT
5625             " bytes", G_STRFUNC, agent, local_message.length);
5626
5627         if (local_message.length > 0) {
5628           nice_component_emit_io_callback (agent, component, local_buf,
5629               local_message.length);
5630         }
5631       }
5632
5633       if (g_source_is_destroyed (g_main_current_source ())) {
5634         nice_debug ("Component IO source disappeared during the callback");
5635         goto out;
5636       }
5637       has_io_callback = nice_component_has_io_callback (component);
5638     }
5639   } else if (component->recv_messages != NULL) {
5640     RecvStatus retval;
5641
5642     /* Don’t want to trample over partially-valid buffers. */
5643     g_assert_cmpuint (component->recv_messages_iter.buffer, ==, 0);
5644     g_assert_cmpint (component->recv_messages_iter.offset, ==, 0);
5645
5646     while (!nice_input_message_iter_is_at_end (&component->recv_messages_iter,
5647         component->recv_messages, component->n_recv_messages)) {
5648       /* Receive a single message. This will receive it into the given
5649        * user-provided #NiceInputMessage, which it’s the user’s responsibility
5650        * to ensure is big enough to avoid data loss (since we’re in non-reliable
5651        * mode). Iterate to receive as many messages as possible.
5652        *
5653        * STUN packets will be parsed in-place. */
5654       retval = agent_recv_message_unlocked (agent, stream, component,
5655           socket_source->socket,
5656           &component->recv_messages[component->recv_messages_iter.message]);
5657
5658       nice_debug_verbose ("%s: %p: received %d valid messages", G_STRFUNC, agent,
5659           retval);
5660
5661       if (retval == RECV_SUCCESS) {
5662         /* Successfully received a single message. */
5663         component->recv_messages_iter.message++;
5664         g_clear_error (component->recv_buf_error);
5665       } else if (retval == RECV_WOULD_BLOCK) {
5666         /* EWOULDBLOCK. */
5667         if (component->recv_messages_iter.message == 0 &&
5668             component->recv_buf_error != NULL &&
5669             *component->recv_buf_error == NULL) {
5670           g_set_error_literal (component->recv_buf_error, G_IO_ERROR,
5671               G_IO_ERROR_WOULD_BLOCK, g_strerror (EAGAIN));
5672         }
5673         break;
5674       } else if (retval == RECV_ERROR) {
5675         /* Other error. */
5676         remove_source = TRUE;
5677         break;
5678       } /* else if (retval == RECV_OOB) { ignore me and continue; } */
5679     }
5680   }
5681
5682 done:
5683
5684   if (remove_source)
5685     nice_component_remove_socket (agent, component, socket_source->socket);
5686
5687   /* If we’re in the middle of a read, don’t emit any signals, or we could cause
5688    * re-entrancy by (e.g.) emitting component-state-changed and having the
5689    * client perform a read. */
5690   if (component->n_recv_messages == 0 && component->recv_messages == NULL) {
5691     agent_unlock_and_emit (agent);
5692   } else {
5693     agent_unlock (agent);
5694   }
5695
5696   g_object_unref (agent);
5697
5698   return !remove_source;
5699
5700 out:
5701   agent_unlock_and_emit (agent);
5702
5703   g_object_unref (agent);
5704
5705   return G_SOURCE_REMOVE;
5706 }
5707
5708 NICEAPI_EXPORT gboolean
5709 nice_agent_attach_recv (
5710   NiceAgent *agent,
5711   guint stream_id,
5712   guint component_id,
5713   GMainContext *ctx,
5714   NiceAgentRecvFunc func,
5715   gpointer data)
5716 {
5717   NiceComponent *component = NULL;
5718   NiceStream *stream = NULL;
5719   gboolean ret = FALSE;
5720
5721   g_return_val_if_fail (NICE_IS_AGENT (agent), FALSE);
5722   g_return_val_if_fail (stream_id >= 1, FALSE);
5723   g_return_val_if_fail (component_id >= 1, FALSE);
5724
5725   agent_lock (agent);
5726
5727   /* attach candidates */
5728
5729   /* step: check that params specify an existing pair */
5730   if (!agent_find_component (agent, stream_id, component_id, &stream, &component)) {
5731     g_warning ("Could not find component %u in stream %u", component_id,
5732         stream_id);
5733     goto done;
5734   }
5735
5736   if (ctx == NULL)
5737     ctx = g_main_context_default ();
5738
5739   /* Set the component’s I/O context. */
5740   nice_component_set_io_context (component, ctx);
5741   nice_component_set_io_callback (component, func, data, NULL, 0, NULL);
5742   ret = TRUE;
5743
5744   if (func) {
5745     /* If we got detached, maybe our readable callback didn't finish reading
5746      * all available data in the pseudotcp, so we need to make sure we free
5747      * our recv window, so the readable callback can be triggered again on the
5748      * next incoming data.
5749      * but only do this if we know we're already readable, otherwise we might
5750      * trigger an error in the initial, pre-connection attach. */
5751     if (agent->reliable && !pseudo_tcp_socket_is_closed (component->tcp) &&
5752         component->tcp_readable)
5753       pseudo_tcp_socket_readable (component->tcp, component);
5754   }
5755
5756  done:
5757   agent_unlock_and_emit (agent);
5758   return ret;
5759 }
5760
5761 NICEAPI_EXPORT gboolean
5762 nice_agent_set_selected_pair (
5763   NiceAgent *agent,
5764   guint stream_id,
5765   guint component_id,
5766   const gchar *lfoundation,
5767   const gchar *rfoundation)
5768 {
5769   NiceComponent *component;
5770   NiceStream *stream;
5771   CandidatePair pair;
5772   gboolean ret = FALSE;
5773
5774   g_return_val_if_fail (NICE_IS_AGENT (agent), FALSE);
5775   g_return_val_if_fail (stream_id >= 1, FALSE);
5776   g_return_val_if_fail (component_id >= 1, FALSE);
5777   g_return_val_if_fail (lfoundation, FALSE);
5778   g_return_val_if_fail (rfoundation, FALSE);
5779
5780   agent_lock (agent);
5781
5782   /* step: check that params specify an existing pair */
5783   if (!agent_find_component (agent, stream_id, component_id, &stream, &component)) {
5784     goto done;
5785   }
5786
5787   if (!nice_component_find_pair (component, agent, lfoundation, rfoundation, &pair)){
5788     goto done;
5789   }
5790
5791   /* step: stop connectivity checks (note: for the whole stream) */
5792   conn_check_prune_stream (agent, stream);
5793
5794   if (agent->reliable && !nice_socket_is_reliable (pair.local->sockptr) &&
5795       pseudo_tcp_socket_is_closed (component->tcp)) {
5796     nice_debug ("Agent %p: not setting selected pair for s%d:%d because "
5797         "pseudo tcp socket does not exist in reliable mode", agent,
5798         stream->id, component->id);
5799     goto done;
5800   }
5801
5802   /* step: change component state; we could be in STATE_DISCONNECTED; skip
5803    * STATE_GATHERING and continue through the states to give client code a nice
5804    * logical progression. See http://phabricator.freedesktop.org/D218 for
5805    * discussion. */
5806   if (component->state < NICE_COMPONENT_STATE_CONNECTING ||
5807       component->state == NICE_COMPONENT_STATE_FAILED)
5808     agent_signal_component_state_change (agent, stream_id, component_id,
5809         NICE_COMPONENT_STATE_CONNECTING);
5810   if (component->state < NICE_COMPONENT_STATE_CONNECTED)
5811     agent_signal_component_state_change (agent, stream_id, component_id,
5812         NICE_COMPONENT_STATE_CONNECTED);
5813   agent_signal_component_state_change (agent, stream_id, component_id,
5814       NICE_COMPONENT_STATE_READY);
5815
5816   /* step: set the selected pair */
5817   nice_component_update_selected_pair (agent, component, &pair);
5818   agent_signal_new_selected_pair (agent, stream_id, component_id,
5819       pair.local, pair.remote);
5820
5821   ret = TRUE;
5822
5823  done:
5824   agent_unlock_and_emit (agent);
5825   return ret;
5826 }
5827
5828 NICEAPI_EXPORT gboolean
5829 nice_agent_get_selected_pair (NiceAgent *agent, guint stream_id,
5830     guint component_id, NiceCandidate **local, NiceCandidate **remote)
5831 {
5832   NiceComponent *component;
5833   NiceStream *stream;
5834   gboolean ret = FALSE;
5835
5836   g_return_val_if_fail (NICE_IS_AGENT (agent), FALSE);
5837   g_return_val_if_fail (stream_id >= 1, FALSE);
5838   g_return_val_if_fail (component_id >= 1, FALSE);
5839   g_return_val_if_fail (local != NULL, FALSE);
5840   g_return_val_if_fail (remote != NULL, FALSE);
5841
5842   agent_lock (agent);
5843
5844   /* step: check that params specify an existing pair */
5845   if (!agent_find_component (agent, stream_id, component_id,
5846           &stream, &component))
5847     goto done;
5848
5849   if (component->selected_pair.local && component->selected_pair.remote) {
5850     *local = component->selected_pair.local;
5851     *remote = component->selected_pair.remote;
5852     ret = TRUE;
5853   }
5854
5855  done:
5856   agent_unlock_and_emit (agent);
5857
5858   return ret;
5859 }
5860
5861 NICEAPI_EXPORT GSocket *
5862 nice_agent_get_selected_socket (NiceAgent *agent, guint stream_id,
5863     guint component_id)
5864 {
5865   NiceComponent *component;
5866   NiceStream *stream;
5867   NiceSocket *nice_socket;
5868   GSocket *g_socket = NULL;
5869
5870   g_return_val_if_fail (NICE_IS_AGENT (agent), NULL);
5871   g_return_val_if_fail (stream_id >= 1, NULL);
5872   g_return_val_if_fail (component_id >= 1, NULL);
5873
5874   agent_lock (agent);
5875
5876   /* Reliable streams are pseudotcp or MUST use RFC 4571 framing */
5877   if (agent->reliable)
5878     goto done;
5879
5880   /* step: check that params specify an existing pair */
5881   if (!agent_find_component (agent, stream_id, component_id,
5882           &stream, &component))
5883     goto done;
5884
5885   if (!component->selected_pair.local || !component->selected_pair.remote)
5886     goto done;
5887
5888   if (component->selected_pair.local->type == NICE_CANDIDATE_TYPE_RELAYED)
5889     goto done;
5890
5891   /* ICE-TCP requires RFC4571 framing, even if unreliable */
5892   if (component->selected_pair.local->transport != NICE_CANDIDATE_TRANSPORT_UDP)
5893     goto done;
5894
5895   nice_socket = (NiceSocket *)component->selected_pair.local->sockptr;
5896   if (nice_socket->fileno)
5897     g_socket = g_object_ref (nice_socket->fileno);
5898
5899  done:
5900   agent_unlock_and_emit (agent);
5901
5902   return g_socket;
5903 }
5904
5905 typedef struct _TimeoutData
5906 {
5907   GWeakRef/*<NiceAgent>*/ agent_ref;
5908   NiceTimeoutLockedCallback function;
5909   gpointer user_data;
5910 } TimeoutData;
5911
5912 static void
5913 timeout_data_destroy (TimeoutData *data)
5914 {
5915   g_weak_ref_clear (&data->agent_ref);
5916   g_slice_free (TimeoutData, data);
5917 }
5918
5919 static TimeoutData *
5920 timeout_data_new (NiceAgent *agent, NiceTimeoutLockedCallback function,
5921     gpointer user_data)
5922 {
5923   TimeoutData *data = g_slice_new0 (TimeoutData);
5924
5925   g_weak_ref_init (&data->agent_ref, agent);
5926   data->function = function;
5927   data->user_data = user_data;
5928
5929   return data;
5930 }
5931
5932 static gboolean
5933 timeout_cb (gpointer user_data)
5934 {
5935   TimeoutData *data = user_data;
5936   NiceAgent *agent;
5937   gboolean ret = G_SOURCE_REMOVE;
5938
5939   agent = g_weak_ref_get (&data->agent_ref);
5940   if (agent == NULL) {
5941     return G_SOURCE_REMOVE;
5942   }
5943
5944   agent_lock (agent);
5945
5946   /* A race condition might happen where the mutex above waits for the lock
5947    * and in the meantime another thread destroys the source.
5948    * In that case, we don't need to run the function since it should
5949    * have been cancelled */
5950   if (g_source_is_destroyed (g_main_current_source ())) {
5951     nice_debug ("Source was destroyed. Avoided race condition in timeout_cb");
5952
5953     agent_unlock (agent);
5954     goto end;
5955   }
5956
5957   ret = data->function (agent, data->user_data);
5958
5959   agent_unlock_and_emit (agent);
5960
5961  end:
5962   g_object_unref (agent);
5963
5964   return ret;
5965 }
5966
5967 /* Create a new timer GSource with the given @name, @interval, callback
5968  * @function and @data, and assign it to @out, destroying and freeing any
5969  * existing #GSource in @out first.
5970  *
5971  * This guarantees that a timer won’t be overwritten without being destroyed.
5972  *
5973  * @interval is given in milliseconds.
5974  */
5975 static void agent_timeout_add_with_context_internal (NiceAgent *agent,
5976     GSource **out, const gchar *name, guint interval, gboolean seconds,
5977     NiceTimeoutLockedCallback function, gpointer user_data)
5978 {
5979   GSource *source;
5980   TimeoutData *data;
5981
5982   g_return_if_fail (function != NULL);
5983   g_return_if_fail (out != NULL);
5984
5985   /* Destroy any existing source. */
5986   if (*out != NULL) {
5987     g_source_destroy (*out);
5988     g_source_unref (*out);
5989     *out = NULL;
5990   }
5991
5992   /* Create the new source. */
5993   if (seconds)
5994     source = g_timeout_source_new_seconds (interval);
5995   else
5996     source = g_timeout_source_new (interval);
5997
5998   g_source_set_name (source, name);
5999   data = timeout_data_new (agent, function, user_data);
6000   g_source_set_callback (source, timeout_cb, data,
6001       (GDestroyNotify)timeout_data_destroy);
6002   g_source_attach (source, agent->main_context);
6003
6004   /* Return it! */
6005   *out = source;
6006 }
6007
6008 void agent_timeout_add_with_context (NiceAgent *agent,
6009     GSource **out, const gchar *name, guint interval,
6010     NiceTimeoutLockedCallback function, gpointer user_data)
6011 {
6012   agent_timeout_add_with_context_internal (agent, out, name, interval, FALSE,
6013       function, user_data);
6014 }
6015
6016 void agent_timeout_add_seconds_with_context (NiceAgent *agent,
6017     GSource **out, const gchar *name, guint interval,
6018     NiceTimeoutLockedCallback function, gpointer user_data)
6019 {
6020   agent_timeout_add_with_context_internal (agent, out, name, interval, TRUE,
6021       function, user_data);
6022 }
6023
6024 NICEAPI_EXPORT gboolean
6025 nice_agent_set_selected_remote_candidate (
6026   NiceAgent *agent,
6027   guint stream_id,
6028   guint component_id,
6029   NiceCandidate *candidate)
6030 {
6031   NiceComponent *component;
6032   NiceStream *stream;
6033   NiceCandidate *lcandidate = NULL;
6034   gboolean ret = FALSE;
6035   NiceCandidate *local = NULL, *remote = NULL;
6036   guint64 priority;
6037
6038   g_return_val_if_fail (NICE_IS_AGENT (agent), FALSE);
6039   g_return_val_if_fail (stream_id != 0, FALSE);
6040   g_return_val_if_fail (component_id != 0, FALSE);
6041   g_return_val_if_fail (candidate != NULL, FALSE);
6042
6043   agent_lock (agent);
6044
6045   /* step: check if the component exists*/
6046   if (!agent_find_component (agent, stream_id, component_id, &stream, &component)) {
6047     goto done;
6048   }
6049
6050   /* step: stop connectivity checks (note: for the whole stream) */
6051   conn_check_prune_stream (agent, stream);
6052
6053   /* Store previous selected pair */
6054   local = component->selected_pair.local;
6055   remote = component->selected_pair.remote;
6056   priority = component->selected_pair.priority;
6057
6058   /* step: set the selected pair */
6059   lcandidate = nice_component_set_selected_remote_candidate (component, agent,
6060       candidate);
6061   if (!lcandidate)
6062     goto done;
6063
6064   if (agent->reliable && !nice_socket_is_reliable (lcandidate->sockptr) &&
6065       pseudo_tcp_socket_is_closed (component->tcp)) {
6066     nice_debug ("Agent %p: not setting selected remote candidate s%d:%d because"
6067         " pseudo tcp socket does not exist in reliable mode", agent,
6068         stream->id, component->id);
6069     /* Revert back to previous selected pair */
6070     /* FIXME: by doing this, we lose the keepalive tick */
6071     component->selected_pair.local = local;
6072     component->selected_pair.remote = remote;
6073     component->selected_pair.priority = priority;
6074     goto done;
6075   }
6076
6077   /* step: change component state; we could be in STATE_DISCONNECTED; skip
6078    * STATE_GATHERING and continue through the states to give client code a nice
6079    * logical progression. See http://phabricator.freedesktop.org/D218 for
6080    * discussion. */
6081   if (component->state < NICE_COMPONENT_STATE_CONNECTING ||
6082       component->state == NICE_COMPONENT_STATE_FAILED)
6083     agent_signal_component_state_change (agent, stream_id, component_id,
6084         NICE_COMPONENT_STATE_CONNECTING);
6085   if (component->state < NICE_COMPONENT_STATE_CONNECTED)
6086     agent_signal_component_state_change (agent, stream_id, component_id,
6087         NICE_COMPONENT_STATE_CONNECTED);
6088   agent_signal_component_state_change (agent, stream_id, component_id,
6089       NICE_COMPONENT_STATE_READY);
6090
6091   agent_signal_new_selected_pair (agent, stream_id, component_id,
6092       lcandidate, candidate);
6093
6094   ret = TRUE;
6095
6096  done:
6097   agent_unlock_and_emit (agent);
6098   return ret;
6099 }
6100
6101 void
6102 _priv_set_socket_tos (NiceAgent *agent, NiceSocket *sock, gint tos)
6103 {
6104   if (sock->fileno == NULL)
6105     return;
6106
6107   if (setsockopt (g_socket_get_fd (sock->fileno), IPPROTO_IP,
6108           IP_TOS, (const char *) &tos, sizeof (tos)) < 0) {
6109     nice_debug ("Agent %p: Could not set socket ToS: %s", agent,
6110         g_strerror (errno));
6111   }
6112 #ifdef IPV6_TCLASS
6113   if (setsockopt (g_socket_get_fd (sock->fileno), IPPROTO_IPV6,
6114           IPV6_TCLASS, (const char *) &tos, sizeof (tos)) < 0) {
6115     nice_debug ("Agent %p: Could not set IPV6 socket ToS: %s", agent,
6116         g_strerror (errno));
6117   }
6118 #endif
6119 }
6120
6121
6122 NICEAPI_EXPORT void
6123 nice_agent_set_stream_tos (NiceAgent *agent,
6124   guint stream_id, gint tos)
6125 {
6126   GSList *i, *j;
6127   NiceStream *stream;
6128
6129   g_return_if_fail (NICE_IS_AGENT (agent));
6130   g_return_if_fail (stream_id >= 1);
6131
6132   agent_lock (agent);
6133
6134   stream = agent_find_stream (agent, stream_id);
6135   if (stream == NULL)
6136     goto done;
6137
6138   stream->tos = tos;
6139   for (i = stream->components; i; i = i->next) {
6140     NiceComponent *component = i->data;
6141
6142     for (j = component->local_candidates; j; j = j->next) {
6143       NiceCandidate *local_candidate = j->data;
6144
6145       _priv_set_socket_tos (agent, local_candidate->sockptr, tos);
6146     }
6147   }
6148
6149  done:
6150   agent_unlock_and_emit (agent);
6151 }
6152
6153 NICEAPI_EXPORT void
6154 nice_agent_set_software (NiceAgent *agent, const gchar *software)
6155 {
6156   g_return_if_fail (NICE_IS_AGENT (agent));
6157
6158   agent_lock (agent);
6159
6160   g_free (agent->software_attribute);
6161   if (software)
6162     agent->software_attribute = g_strdup_printf ("%s/%s",
6163         software, PACKAGE_STRING);
6164   else
6165     agent->software_attribute = NULL;
6166
6167   nice_agent_reset_all_stun_agents (agent, TRUE);
6168
6169   agent_unlock_and_emit (agent);
6170 }
6171
6172 NICEAPI_EXPORT gboolean
6173 nice_agent_set_stream_name (NiceAgent *agent, guint stream_id,
6174     const gchar *name)
6175 {
6176   NiceStream *stream_to_name = NULL;
6177   GSList *i;
6178   gboolean ret = FALSE;
6179
6180   g_return_val_if_fail (NICE_IS_AGENT (agent), FALSE);
6181   g_return_val_if_fail (stream_id >= 1, FALSE);
6182   g_return_val_if_fail (name, FALSE);
6183
6184   if (strcmp (name, "audio") &&
6185       strcmp (name, "video") &&
6186       strcmp (name, "text") &&
6187       strcmp (name, "application") &&
6188       strcmp (name, "message") &&
6189       strcmp (name, "image")) {
6190     g_critical ("Stream name %s will produce invalid SDP, only \"audio\","
6191         " \"video\", \"text\", \"application\", \"image\" and \"message\""
6192         " are valid", name);
6193   }
6194
6195   agent_lock (agent);
6196
6197   for (i = agent->streams; i; i = i->next) {
6198     NiceStream *stream = i->data;
6199
6200     if (stream->id != stream_id &&
6201         g_strcmp0 (stream->name, name) == 0)
6202       goto done;
6203     else if (stream->id == stream_id)
6204       stream_to_name = stream;
6205   }
6206
6207   if (stream_to_name == NULL)
6208     goto done;
6209
6210   if (stream_to_name->name)
6211     g_free (stream_to_name->name);
6212   stream_to_name->name = g_strdup (name);
6213   ret = TRUE;
6214
6215  done:
6216   agent_unlock_and_emit (agent);
6217
6218   return ret;
6219 }
6220
6221 NICEAPI_EXPORT const gchar *
6222 nice_agent_get_stream_name (NiceAgent *agent, guint stream_id)
6223 {
6224   NiceStream *stream;
6225   gchar *name = NULL;
6226
6227   g_return_val_if_fail (NICE_IS_AGENT (agent), NULL);
6228   g_return_val_if_fail (stream_id >= 1, NULL);
6229
6230   agent_lock (agent);
6231
6232   stream = agent_find_stream (agent, stream_id);
6233   if (stream == NULL)
6234     goto done;
6235
6236   name = stream->name;
6237
6238  done:
6239   agent_unlock_and_emit (agent);
6240   return name;
6241 }
6242
6243 static NiceCandidate *
6244 _get_default_local_candidate_locked (NiceAgent *agent,
6245     NiceStream *stream,  NiceComponent *component)
6246 {
6247   GSList *i;
6248   NiceCandidate *default_candidate = NULL;
6249   NiceCandidate *default_rtp_candidate = NULL;
6250
6251   if (component->id != NICE_COMPONENT_TYPE_RTP) {
6252     NiceComponent *rtp_component;
6253
6254     if (!agent_find_component (agent, stream->id, NICE_COMPONENT_TYPE_RTP,
6255             NULL, &rtp_component))
6256       goto done;
6257
6258     default_rtp_candidate = _get_default_local_candidate_locked (agent, stream,
6259         rtp_component);
6260     if (default_rtp_candidate == NULL)
6261       goto done;
6262   }
6263
6264
6265   for (i = component->local_candidates; i; i = i->next) {
6266     NiceCandidate *local_candidate = i->data;
6267
6268     if (agent->force_relay &&
6269         local_candidate->type != NICE_CANDIDATE_TYPE_RELAYED)
6270       continue;
6271
6272     /* Only check for ipv4 candidates */
6273     if (nice_address_ip_version (&local_candidate->addr) != 4)
6274       continue;
6275     if (component->id == NICE_COMPONENT_TYPE_RTP) {
6276       if (default_candidate == NULL ||
6277           local_candidate->priority < default_candidate->priority) {
6278         default_candidate = local_candidate;
6279       }
6280     } else if (strncmp (local_candidate->foundation,
6281             default_rtp_candidate->foundation,
6282             NICE_CANDIDATE_MAX_FOUNDATION) == 0) {
6283       default_candidate = local_candidate;
6284       break;
6285     }
6286   }
6287
6288  done:
6289   return default_candidate;
6290 }
6291
6292 NICEAPI_EXPORT NiceCandidate *
6293 nice_agent_get_default_local_candidate (NiceAgent *agent,
6294     guint stream_id,  guint component_id)
6295 {
6296   NiceStream *stream = NULL;
6297   NiceComponent *component = NULL;
6298   NiceCandidate *default_candidate = NULL;
6299
6300   g_return_val_if_fail (NICE_IS_AGENT (agent), NULL);
6301   g_return_val_if_fail (stream_id >= 1, NULL);
6302   g_return_val_if_fail (component_id >= 1, NULL);
6303
6304   agent_lock (agent);
6305
6306   /* step: check if the component exists*/
6307   if (!agent_find_component (agent, stream_id, component_id,
6308           &stream, &component))
6309     goto done;
6310
6311   default_candidate = _get_default_local_candidate_locked (agent, stream,
6312       component);
6313   if (default_candidate)
6314     default_candidate = nice_candidate_copy (default_candidate);
6315
6316  done:
6317   agent_unlock_and_emit (agent);
6318
6319   return default_candidate;
6320 }
6321
6322 static const gchar *
6323 _cand_type_to_sdp (NiceCandidateType type) {
6324   switch(type) {
6325     case NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE:
6326       return "srflx";
6327     case NICE_CANDIDATE_TYPE_PEER_REFLEXIVE:
6328       return "prflx";
6329     case NICE_CANDIDATE_TYPE_RELAYED:
6330       return "relay";
6331     case NICE_CANDIDATE_TYPE_HOST:
6332     default:
6333       return "host";
6334   }
6335 }
6336
6337 static const gchar *
6338 _transport_to_sdp (NiceCandidateTransport type) {
6339   switch(type) {
6340     case NICE_CANDIDATE_TRANSPORT_UDP:
6341       return "UDP";
6342     case NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE:
6343     case NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE:
6344     case NICE_CANDIDATE_TRANSPORT_TCP_SO:
6345       return "TCP";
6346     default:
6347       return "???";
6348   }
6349 }
6350
6351 static const gchar *
6352 _transport_to_sdp_tcptype (NiceCandidateTransport type) {
6353   switch(type) {
6354     case NICE_CANDIDATE_TRANSPORT_UDP:
6355       return "";
6356     case NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE:
6357       return "active";
6358     case NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE:
6359       return "passive";
6360     case NICE_CANDIDATE_TRANSPORT_TCP_SO:
6361       return "so";
6362     default:
6363       return "";
6364   }
6365 }
6366
6367 static void
6368 _generate_candidate_sdp (NiceAgent *agent,
6369     NiceCandidate *candidate, GString *sdp)
6370 {
6371   gchar ip4[INET6_ADDRSTRLEN];
6372   guint16 port;
6373
6374   nice_address_to_string (&candidate->addr, ip4);
6375   port = nice_address_get_port (&candidate->addr);
6376   g_string_append_printf (sdp, "a=candidate:%.*s %d %s %d %s %d",
6377       NICE_CANDIDATE_MAX_FOUNDATION, candidate->foundation,
6378       candidate->component_id,
6379       _transport_to_sdp (candidate->transport),
6380       candidate->priority, ip4, port == 0 ? 9 : port);
6381   g_string_append_printf (sdp, " typ %s", _cand_type_to_sdp (candidate->type));
6382   if (nice_address_is_valid (&candidate->base_addr) &&
6383       !nice_address_equal (&candidate->addr, &candidate->base_addr)) {
6384     port = nice_address_get_port (&candidate->base_addr);
6385     nice_address_to_string (&candidate->base_addr, ip4);
6386     g_string_append_printf (sdp, " raddr %s rport %d", ip4,
6387         port == 0 ? 9 : port);
6388   }
6389   if (candidate->transport != NICE_CANDIDATE_TRANSPORT_UDP) {
6390     g_string_append_printf (sdp, " tcptype %s",
6391         _transport_to_sdp_tcptype (candidate->transport));
6392   }
6393 }
6394
6395 static void
6396 _generate_stream_sdp (NiceAgent *agent, NiceStream *stream,
6397     GString *sdp, gboolean include_non_ice)
6398 {
6399   GSList *i, *j;
6400
6401   if (include_non_ice) {
6402     NiceAddress rtp, rtcp;
6403     gchar ip4[INET6_ADDRSTRLEN] = "";
6404
6405     nice_address_init (&rtp);
6406     nice_address_set_ipv4 (&rtp, 0);
6407     nice_address_init (&rtcp);
6408     nice_address_set_ipv4 (&rtcp, 0);
6409
6410     /* Find default candidates */
6411     for (i = stream->components; i; i = i->next) {
6412       NiceComponent *component = i->data;
6413       NiceCandidate *default_candidate;
6414
6415       if (component->id == NICE_COMPONENT_TYPE_RTP) {
6416         default_candidate = _get_default_local_candidate_locked (agent, stream,
6417             component);
6418         if (default_candidate)
6419           rtp = default_candidate->addr;
6420       } else if (component->id == NICE_COMPONENT_TYPE_RTCP) {
6421         default_candidate = _get_default_local_candidate_locked (agent, stream,
6422             component);
6423         if (default_candidate)
6424           rtcp = default_candidate->addr;
6425       }
6426     }
6427
6428     nice_address_to_string (&rtp, ip4);
6429     g_string_append_printf (sdp, "m=%s %d ICE/SDP\n",
6430         stream->name ? stream->name : "-", nice_address_get_port (&rtp));
6431     g_string_append_printf (sdp, "c=IN IP4 %s\n", ip4);
6432     if (nice_address_get_port (&rtcp) != 0)
6433       g_string_append_printf (sdp, "a=rtcp:%d\n",
6434           nice_address_get_port (&rtcp));
6435   }
6436
6437   g_string_append_printf (sdp, "a=ice-ufrag:%s\n", stream->local_ufrag);
6438   g_string_append_printf (sdp, "a=ice-pwd:%s\n", stream->local_password);
6439
6440   for (i = stream->components; i; i = i->next) {
6441     NiceComponent *component = i->data;
6442
6443     for (j = component->local_candidates; j; j = j->next) {
6444       NiceCandidate *candidate = j->data;
6445
6446       if (agent->force_relay && candidate->type != NICE_CANDIDATE_TYPE_RELAYED)
6447         continue;
6448
6449       _generate_candidate_sdp (agent, candidate, sdp);
6450       g_string_append (sdp, "\n");
6451     }
6452   }
6453 }
6454
6455 NICEAPI_EXPORT gchar *
6456 nice_agent_generate_local_sdp (NiceAgent *agent)
6457 {
6458   GString * sdp = g_string_new (NULL);
6459   GSList *i;
6460
6461   g_return_val_if_fail (NICE_IS_AGENT (agent), NULL);
6462
6463   agent_lock (agent);
6464
6465   for (i = agent->streams; i; i = i->next) {
6466     NiceStream *stream = i->data;
6467
6468     _generate_stream_sdp (agent, stream, sdp, TRUE);
6469   }
6470
6471   agent_unlock_and_emit (agent);
6472
6473   return g_string_free (sdp, FALSE);
6474 }
6475
6476 NICEAPI_EXPORT gchar *
6477 nice_agent_generate_local_stream_sdp (NiceAgent *agent, guint stream_id,
6478     gboolean include_non_ice)
6479 {
6480   GString *sdp = NULL;
6481   gchar *ret = NULL;
6482   NiceStream *stream;
6483
6484   g_return_val_if_fail (NICE_IS_AGENT (agent), NULL);
6485   g_return_val_if_fail (stream_id >= 1, NULL);
6486
6487   agent_lock (agent);
6488
6489   stream = agent_find_stream (agent, stream_id);
6490   if (stream == NULL)
6491     goto done;
6492
6493   sdp = g_string_new (NULL);
6494   _generate_stream_sdp (agent, stream, sdp, include_non_ice);
6495   ret = g_string_free (sdp, FALSE);
6496
6497  done:
6498   agent_unlock_and_emit (agent);
6499
6500   return ret;
6501 }
6502
6503 NICEAPI_EXPORT gchar *
6504 nice_agent_generate_local_candidate_sdp (NiceAgent *agent,
6505     NiceCandidate *candidate)
6506 {
6507   GString *sdp = NULL;
6508
6509   g_return_val_if_fail (NICE_IS_AGENT (agent), NULL);
6510   g_return_val_if_fail (candidate != NULL, NULL);
6511
6512   agent_lock (agent);
6513
6514   sdp = g_string_new (NULL);
6515   _generate_candidate_sdp (agent, candidate, sdp);
6516
6517   agent_unlock_and_emit (agent);
6518
6519   return g_string_free (sdp, FALSE);
6520 }
6521
6522 NICEAPI_EXPORT gint
6523 nice_agent_parse_remote_sdp (NiceAgent *agent, const gchar *sdp)
6524 {
6525   NiceStream *current_stream = NULL;
6526   gchar **sdp_lines = NULL;
6527   GSList *stream_item = NULL;
6528   gint i;
6529   gint ret = 0;
6530
6531   g_return_val_if_fail (NICE_IS_AGENT (agent), -1);
6532   g_return_val_if_fail (sdp != NULL, -1);
6533
6534   agent_lock (agent);
6535
6536   sdp_lines = g_strsplit (sdp, "\n", 0);
6537   for (i = 0; sdp_lines && sdp_lines[i]; i++) {
6538     if (g_str_has_prefix (sdp_lines[i], "m=")) {
6539       if (stream_item == NULL)
6540         stream_item = agent->streams;
6541       else
6542         stream_item = stream_item->next;
6543       if (!stream_item) {
6544         g_critical("More streams in SDP than in agent");
6545         ret = -1;
6546         goto done;
6547       }
6548       current_stream = stream_item->data;
6549    } else if (g_str_has_prefix (sdp_lines[i], "a=ice-ufrag:")) {
6550       if (current_stream == NULL) {
6551         ret = -1;
6552         goto done;
6553       }
6554       g_strlcpy (current_stream->remote_ufrag, sdp_lines[i] + 12,
6555           NICE_STREAM_MAX_UFRAG);
6556     } else if (g_str_has_prefix (sdp_lines[i], "a=ice-pwd:")) {
6557       if (current_stream == NULL) {
6558         ret = -1;
6559         goto done;
6560       }
6561       g_strlcpy (current_stream->remote_password, sdp_lines[i] + 10,
6562           NICE_STREAM_MAX_PWD);
6563     } else if (g_str_has_prefix (sdp_lines[i], "a=candidate:")) {
6564       NiceCandidate *candidate = NULL;
6565       NiceComponent *component = NULL;
6566       GSList *cands = NULL;
6567       gint added;
6568
6569       if (current_stream == NULL) {
6570         ret = -1;
6571         goto done;
6572       }
6573       candidate = nice_agent_parse_remote_candidate_sdp (agent,
6574           current_stream->id, sdp_lines[i]);
6575       if (candidate == NULL) {
6576         ret = -1;
6577         goto done;
6578       }
6579
6580       if (!agent_find_component (agent, candidate->stream_id,
6581               candidate->component_id, NULL, &component)) {
6582         nice_candidate_free (candidate);
6583         ret = -1;
6584         goto done;
6585       }
6586       cands = g_slist_prepend (cands, candidate);
6587       added = _set_remote_candidates_locked (agent, current_stream,
6588           component, cands);
6589       g_slist_free_full(cands, (GDestroyNotify)&nice_candidate_free);
6590       if (added > 0)
6591         ret++;
6592     }
6593   }
6594
6595  done:
6596   if (sdp_lines)
6597     g_strfreev(sdp_lines);
6598
6599   agent_unlock_and_emit (agent);
6600
6601   return ret;
6602 }
6603
6604 NICEAPI_EXPORT GSList *
6605 nice_agent_parse_remote_stream_sdp (NiceAgent *agent, guint stream_id,
6606     const gchar *sdp, gchar **ufrag, gchar **pwd)
6607 {
6608   NiceStream *stream = NULL;
6609   gchar **sdp_lines = NULL;
6610   GSList *candidates = NULL;
6611   gint i;
6612
6613   g_return_val_if_fail (NICE_IS_AGENT (agent), NULL);
6614   g_return_val_if_fail (stream_id >= 1, NULL);
6615   g_return_val_if_fail (sdp != NULL, NULL);
6616
6617   agent_lock (agent);
6618
6619   stream = agent_find_stream (agent, stream_id);
6620   if (stream == NULL) {
6621     goto done;
6622   }
6623
6624   sdp_lines = g_strsplit (sdp, "\n", 0);
6625   for (i = 0; sdp_lines && sdp_lines[i]; i++) {
6626     if (ufrag && g_str_has_prefix (sdp_lines[i], "a=ice-ufrag:")) {
6627       *ufrag = g_strdup (sdp_lines[i] + 12);
6628     } else if (pwd && g_str_has_prefix (sdp_lines[i], "a=ice-pwd:")) {
6629       *pwd = g_strdup (sdp_lines[i] + 10);
6630     } else if (g_str_has_prefix (sdp_lines[i], "a=candidate:")) {
6631       NiceCandidate *candidate = NULL;
6632
6633       candidate = nice_agent_parse_remote_candidate_sdp (agent, stream->id,
6634           sdp_lines[i]);
6635       if (candidate == NULL) {
6636         g_slist_free_full(candidates, (GDestroyNotify)&nice_candidate_free);
6637         candidates = NULL;
6638         break;
6639       }
6640       candidates = g_slist_prepend (candidates, candidate);
6641     }
6642   }
6643
6644  done:
6645   if (sdp_lines)
6646     g_strfreev(sdp_lines);
6647
6648   agent_unlock_and_emit (agent);
6649
6650   return candidates;
6651 }
6652
6653 NICEAPI_EXPORT NiceCandidate *
6654 nice_agent_parse_remote_candidate_sdp (NiceAgent *agent, guint stream_id,
6655     const gchar *sdp)
6656 {
6657   NiceCandidate *candidate = NULL;
6658   int ntype = -1;
6659   gchar **tokens = NULL;
6660   const gchar *foundation = NULL;
6661   guint component_id = 0;
6662   const gchar *transport = NULL;
6663   guint32 priority = 0;
6664   const gchar *addr = NULL;
6665   guint16 port = 0;
6666   const gchar *type = NULL;
6667   const gchar *tcptype = NULL;
6668   const gchar *raddr = NULL;
6669   guint16 rport = 0;
6670   static const gchar *type_names[] = {"host", "srflx", "prflx", "relay"};
6671   NiceCandidateTransport ctransport;
6672   guint i;
6673
6674   g_return_val_if_fail (NICE_IS_AGENT (agent), NULL);
6675   g_return_val_if_fail (stream_id >= 1, NULL);
6676   g_return_val_if_fail (sdp != NULL, NULL);
6677
6678   if (!g_str_has_prefix (sdp, "a=candidate:"))
6679     goto done;
6680
6681   tokens = g_strsplit (sdp + 12, " ", 0);
6682   for (i = 0; tokens && tokens[i]; i++) {
6683     switch (i) {
6684       case 0:
6685         foundation = tokens[i];
6686         break;
6687       case 1:
6688         component_id = (guint) g_ascii_strtoull (tokens[i], NULL, 10);
6689         break;
6690       case 2:
6691         transport = tokens[i];
6692         break;
6693       case 3:
6694         priority = (guint32) g_ascii_strtoull (tokens[i], NULL, 10);
6695         break;
6696       case 4:
6697         addr = tokens[i];
6698         break;
6699       case 5:
6700         port = (guint16) g_ascii_strtoull (tokens[i], NULL, 10);
6701         break;
6702       default:
6703         if (tokens[i + 1] == NULL)
6704           goto done;
6705
6706         if (g_strcmp0 (tokens[i], "typ") == 0) {
6707           type = tokens[i + 1];
6708         } else if (g_strcmp0 (tokens[i], "raddr") == 0) {
6709           raddr = tokens[i + 1];
6710         } else if (g_strcmp0 (tokens[i], "rport") == 0) {
6711           rport = (guint16) g_ascii_strtoull (tokens[i + 1], NULL, 10);
6712         } else if (g_strcmp0 (tokens[i], "tcptype") == 0) {
6713           tcptype = tokens[i + 1];
6714         }
6715         i++;
6716         break;
6717     }
6718   }
6719   if (type == NULL)
6720     goto done;
6721
6722   ntype = -1;
6723   for (i = 0; i < G_N_ELEMENTS (type_names); i++) {
6724     if (g_strcmp0 (type, type_names[i]) == 0) {
6725       ntype = i;
6726       break;
6727     }
6728   }
6729   if (ntype == -1)
6730     goto done;
6731
6732   if (g_ascii_strcasecmp (transport, "UDP") == 0)
6733     ctransport = NICE_CANDIDATE_TRANSPORT_UDP;
6734   else if (g_ascii_strcasecmp (transport, "TCP-SO") == 0)
6735     ctransport = NICE_CANDIDATE_TRANSPORT_TCP_SO;
6736   else if (g_ascii_strcasecmp (transport, "TCP-ACT") == 0)
6737     ctransport = NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE;
6738   else if (g_ascii_strcasecmp (transport, "TCP-PASS") == 0)
6739     ctransport = NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE;
6740   else if (g_ascii_strcasecmp (transport, "TCP") == 0) {
6741     if (g_ascii_strcasecmp (tcptype, "so") == 0)
6742       ctransport = NICE_CANDIDATE_TRANSPORT_TCP_SO;
6743     else if (g_ascii_strcasecmp (tcptype, "active") == 0)
6744       ctransport = NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE;
6745     else if (g_ascii_strcasecmp (tcptype, "passive") == 0)
6746       ctransport = NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE;
6747     else
6748       goto done;
6749   } else
6750     goto done;
6751
6752   candidate = nice_candidate_new(ntype);
6753   candidate->component_id = component_id;
6754   candidate->stream_id = stream_id;
6755   candidate->transport = ctransport;
6756   g_strlcpy(candidate->foundation, foundation, NICE_CANDIDATE_MAX_FOUNDATION);
6757   candidate->priority = priority;
6758
6759   if (!nice_address_set_from_string (&candidate->addr, addr)) {
6760     nice_candidate_free (candidate);
6761     candidate = NULL;
6762     goto done;
6763   }
6764   nice_address_set_port (&candidate->addr, port);
6765
6766   if (raddr && rport) {
6767     if (!nice_address_set_from_string (&candidate->base_addr, raddr)) {
6768       nice_candidate_free (candidate);
6769       candidate = NULL;
6770       goto done;
6771     }
6772     nice_address_set_port (&candidate->base_addr, rport);
6773   }
6774
6775  done:
6776   if (tokens)
6777     g_strfreev(tokens);
6778
6779   return candidate;
6780 }
6781
6782
6783 NICEAPI_EXPORT GIOStream *
6784 nice_agent_get_io_stream (NiceAgent *agent, guint stream_id,
6785     guint component_id)
6786 {
6787   GIOStream *iostream = NULL;
6788   NiceComponent *component;
6789
6790   g_return_val_if_fail (NICE_IS_AGENT (agent), NULL);
6791   g_return_val_if_fail (stream_id >= 1, NULL);
6792   g_return_val_if_fail (component_id >= 1, NULL);
6793
6794   g_return_val_if_fail (agent->reliable, NULL);
6795
6796   agent_lock (agent);
6797
6798   if (!agent_find_component (agent, stream_id, component_id, NULL, &component))
6799     goto done;
6800
6801   if (component->iostream == NULL)
6802     component->iostream = nice_io_stream_new (agent, stream_id, component_id);
6803
6804   iostream = g_object_ref (component->iostream);
6805
6806  done:
6807   agent_unlock_and_emit (agent);
6808
6809   return iostream;
6810 }
6811
6812 NICEAPI_EXPORT gboolean
6813 nice_agent_forget_relays (NiceAgent *agent, guint stream_id, guint component_id)
6814 {
6815   NiceComponent *component;
6816   gboolean ret = TRUE;
6817
6818   g_return_val_if_fail (NICE_IS_AGENT (agent), FALSE);
6819   g_return_val_if_fail (stream_id >= 1, FALSE);
6820   g_return_val_if_fail (component_id >= 1, FALSE);
6821
6822   agent_lock (agent);
6823
6824   if (!agent_find_component (agent, stream_id, component_id, NULL, &component)) {
6825     ret = FALSE;
6826     goto done;
6827   }
6828
6829   nice_component_clean_turn_servers (agent, component);
6830
6831  done:
6832   agent_unlock_and_emit (agent);
6833
6834   return ret;
6835 }
6836
6837 /* Helper function to allow us to send connchecks reliably.
6838  * If the transport is reliable, then we request a reliable send, which will
6839  * either send the data, or queue it in the case of unestablished http/socks5
6840  * proxies or tcp-turn. If the transport is not reliable, then it could be an
6841  * unreliable tcp-bsd, so we still try a reliable send to see if it can succeed
6842  * meaning the message was queued, or if it failed, then it was either udp-bsd
6843  * or turn and so we retry with a non reliable send and let the retransmissions
6844  * take care of the rest.
6845  * This is in order to avoid having to retransmit something if the underlying
6846  * socket layer can queue the message and send it once a connection is
6847  * established.
6848  */
6849 gssize
6850 agent_socket_send (NiceSocket *sock, const NiceAddress *addr, gsize len,
6851     const gchar *buf)
6852 {
6853   if (nice_socket_is_reliable (sock)) {
6854     guint16 rfc4571_frame = htons (len);
6855     GOutputVector local_buf[2] = {{&rfc4571_frame, 2}, { buf, len }};
6856     NiceOutputMessage local_message = { local_buf, 2};
6857     gint ret;
6858
6859     /* ICE-TCP requires that all packets be framed with RFC4571 */
6860     ret = nice_socket_send_messages_reliable (sock, addr, &local_message, 1);
6861     if (ret == 1)
6862       return len;
6863     return ret;
6864   } else {
6865     gssize ret = nice_socket_send_reliable (sock, addr, len, buf);
6866     if (ret < 0)
6867       ret = nice_socket_send (sock, addr, len, buf);
6868     return ret;
6869   }
6870 }
6871
6872 NiceComponentState
6873 nice_agent_get_component_state (NiceAgent *agent,
6874     guint stream_id, guint component_id)
6875 {
6876   NiceComponentState state = NICE_COMPONENT_STATE_FAILED;
6877   NiceComponent *component;
6878
6879   agent_lock (agent);
6880
6881   if (agent_find_component (agent, stream_id, component_id, NULL, &component))
6882     state = component->state;
6883
6884   agent_unlock (agent);
6885
6886   return state;
6887 }
6888
6889 gboolean
6890 nice_agent_peer_candidate_gathering_done (NiceAgent *agent, guint stream_id)
6891 {
6892   NiceStream *stream;
6893   gboolean result = FALSE;
6894
6895   agent_lock (agent);
6896
6897   stream = agent_find_stream (agent, stream_id);
6898   if (stream) {
6899     stream->peer_gathering_done = TRUE;
6900     result = TRUE;
6901   }
6902
6903   agent_unlock (agent);
6904
6905   return result;
6906 }
6907
6908 static gboolean
6909 on_agent_refreshes_pruned (NiceAgent *agent, gpointer user_data)
6910 {
6911   GTask *task = user_data;
6912
6913   /* This is called from a timeout cb with agent lock held */
6914
6915   agent_unlock (agent);
6916
6917   g_task_return_boolean (task, TRUE);
6918   g_object_unref (task);
6919
6920   agent_lock (agent);
6921
6922   return G_SOURCE_REMOVE;
6923 }
6924
6925 void
6926 nice_agent_close_async (NiceAgent *agent, GAsyncReadyCallback callback,
6927     gpointer callback_data)
6928 {
6929   GTask *task;
6930
6931   task = g_task_new (agent, NULL, callback, callback_data);
6932   g_task_set_source_tag (task, nice_agent_close_async);
6933
6934   agent_lock (agent);
6935
6936   refresh_prune_agent_async (agent, on_agent_refreshes_pruned, task);
6937
6938   agent_unlock (agent);
6939 }
6940
6941
6942 NICEAPI_EXPORT GPtrArray *
6943 nice_agent_get_sockets (NiceAgent *agent, guint stream_id, guint component_id)
6944 {
6945   GPtrArray *array = NULL;
6946   NiceComponent *component;
6947
6948   agent_lock (agent);
6949   if (agent_find_component (agent, stream_id, component_id, NULL, &component))
6950     array = nice_component_get_sockets (component);
6951   agent_unlock (agent);
6952
6953   return array;
6954 }