1 /* $Id$ */
2 /*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20 #include <pjnath/ice_strans.h>
21 #include <pjnath/errno.h>
22 #include <pj/addr_resolv.h>
23 #include <pj/array.h>
24 #include <pj/assert.h>
25 #include <pj/ip_helper.h>
26 #include <pj/lock.h>
27 #include <pj/log.h>
28 #include <pj/os.h>
29 #include <pj/pool.h>
30 #include <pj/rand.h>
31 #include <pj/string.h>
32 #include <pj/compat/socket.h>
33
34 #define ENABLE_TRACE 0
35
36 #if defined(ENABLE_TRACE) && (ENABLE_TRACE != 0)
37 # define TRACE_PKT(expr) PJ_LOG(5,expr)
38 #else
39 # define TRACE_PKT(expr)
40 #endif
41
42
43 /* Transport IDs */
44 enum tp_type
45 {
46 TP_NONE,
47 TP_STUN,
48 TP_TURN
49 };
50
51
52 #define CREATE_TP_ID(type, idx) (pj_uint8_t)((type << 6) | idx)
53 #define GET_TP_TYPE(transport_id) ((transport_id & 0xC0) >> 6)
54 #define GET_TP_IDX(transport_id) (transport_id & 0x3F)
55
56
57 /* Candidate's local preference values. This is mostly used to
58 * specify preference among candidates with the same type. Since
59 * we don't have the facility to specify that, we'll just set it
60 * all to the same value.
61 */
62 #if PJNATH_ICE_PRIO_STD
63 # define SRFLX_PREF 65535
64 # define HOST_PREF 65535
65 # define RELAY_PREF 65535
66 #else
67 # define SRFLX_PREF ((1 << PJ_ICE_LOCAL_PREF_BITS) - 1)
68 # define HOST_PREF ((1 << PJ_ICE_LOCAL_PREF_BITS) - 1)
69 # define RELAY_PREF ((1 << PJ_ICE_LOCAL_PREF_BITS) - 1)
70 #endif
71
72
73 /* The candidate type preference when STUN candidate is used */
74 static pj_uint8_t srflx_pref_table[PJ_ICE_CAND_TYPE_MAX] =
75 {
76 #if PJNATH_ICE_PRIO_STD
77 100, /**< PJ_ICE_HOST_PREF */
78 110, /**< PJ_ICE_SRFLX_PREF */
79 126, /**< PJ_ICE_PRFLX_PREF */
80 0 /**< PJ_ICE_RELAYED_PREF */
81 #else
82 /* Keep it to 2 bits */
83 1, /**< PJ_ICE_HOST_PREF */
84 2, /**< PJ_ICE_SRFLX_PREF */
85 3, /**< PJ_ICE_PRFLX_PREF */
86 0 /**< PJ_ICE_RELAYED_PREF */
87 #endif
88 };
89
90
91 /* ICE callbacks */
92 static void on_valid_pair(pj_ice_sess *ice);
93 static void on_ice_complete(pj_ice_sess *ice, pj_status_t status);
94 static pj_status_t ice_tx_pkt(pj_ice_sess *ice,
95 unsigned comp_id,
96 unsigned transport_id,
97 const void *pkt, pj_size_t size,
98 const pj_sockaddr_t *dst_addr,
99 unsigned dst_addr_len);
100 static void ice_rx_data(pj_ice_sess *ice,
101 unsigned comp_id,
102 unsigned transport_id,
103 void *pkt, pj_size_t size,
104 const pj_sockaddr_t *src_addr,
105 unsigned src_addr_len);
106
107
108 /* STUN socket callbacks */
109 /* Notification when incoming packet has been received. */
110 static pj_bool_t stun_on_rx_data(pj_stun_sock *stun_sock,
111 void *pkt,
112 unsigned pkt_len,
113 const pj_sockaddr_t *src_addr,
114 unsigned addr_len);
115 /* Notifification when asynchronous send operation has completed. */
116 static pj_bool_t stun_on_data_sent(pj_stun_sock *stun_sock,
117 pj_ioqueue_op_key_t *send_key,
118 pj_ssize_t sent);
119 /* Notification when the status of the STUN transport has changed. */
120 static pj_bool_t stun_on_status(pj_stun_sock *stun_sock,
121 pj_stun_sock_op op,
122 pj_status_t status);
123
124
125 /* TURN callbacks */
126 static void turn_on_rx_data(pj_turn_sock *turn_sock,
127 void *pkt,
128 unsigned pkt_len,
129 const pj_sockaddr_t *peer_addr,
130 unsigned addr_len);
131 static pj_bool_t turn_on_data_sent(pj_turn_sock *turn_sock,
132 pj_ssize_t sent);
133 static void turn_on_state(pj_turn_sock *turn_sock, pj_turn_state_t old_state,
134 pj_turn_state_t new_state);
135
136
137
138 /* Forward decls */
139 static pj_bool_t on_data_sent(pj_ice_strans *ice_st, pj_ssize_t sent);
140 static void check_pending_send(pj_ice_strans *ice_st);
141 static void ice_st_on_destroy(void *obj);
142 static void destroy_ice_st(pj_ice_strans *ice_st);
143 #define ice_st_perror(ice_st,msg,rc) pjnath_perror(ice_st->obj_name,msg,rc)
144 static void sess_init_update(pj_ice_strans *ice_st);
145
146 /**
147 * This structure describes an ICE stream transport component. A component
148 * in ICE stream transport typically corresponds to a single socket created
149 * for this component, and bound to a specific transport address. This
150 * component may have multiple alias addresses, for example one alias
151 * address for each interfaces in multi-homed host, another for server
152 * reflexive alias, and another for relayed alias. For each transport
153 * address alias, an ICE stream transport candidate (#pj_ice_sess_cand) will
154 * be created, and these candidates will eventually registered to the ICE
155 * session.
156 */
157 typedef struct pj_ice_strans_comp
158 {
159 pj_ice_strans *ice_st; /**< ICE stream transport. */
160 unsigned comp_id; /**< Component ID. */
161
162 struct {
163 pj_stun_sock *sock; /**< STUN transport. */
164 } stun[PJ_ICE_MAX_STUN];
165
166 struct {
167 pj_turn_sock *sock; /**< TURN relay transport. */
168 pj_bool_t log_off; /**< TURN loggin off? */
169 unsigned err_cnt; /**< TURN disconnected count. */
170 } turn[PJ_ICE_MAX_TURN];
171
172 pj_bool_t creating; /**< Is creating the candidates?*/
173 unsigned cand_cnt; /**< # of candidates/aliaes. */
174 pj_ice_sess_cand cand_list[PJ_ICE_ST_MAX_CAND]; /**< Cand array */
175
176 pj_bool_t ipv4_mapped; /**< Is IPv6 addr mapped to IPv4?*/
177 pj_sockaddr dst_addr; /**< Destination address */
178 pj_sockaddr synth_addr; /**< Synthesized dest address */
179 unsigned synth_addr_len;/**< Synthesized dest addr len */
180
181 unsigned default_cand; /**< Default candidate. */
182
183 } pj_ice_strans_comp;
184
185
186 /* Pending send buffer */
187 typedef struct pending_send
188 {
189 void *buffer;
190 unsigned comp_id;
191 pj_size_t data_len;
192 pj_sockaddr dst_addr;
193 int dst_addr_len;
194 } pending_send;
195
196 /**
197 * This structure represents the ICE stream transport.
198 */
199 struct pj_ice_strans
200 {
201 char *obj_name; /**< Log ID. */
202 pj_pool_factory *pf; /**< Pool factory. */
203 pj_pool_t *pool; /**< Pool used by this object. */
204 void *user_data; /**< Application data. */
205 pj_ice_strans_cfg cfg; /**< Configuration. */
206 pj_ice_strans_cb cb; /**< Application callback. */
207 pj_grp_lock_t *grp_lock; /**< Group lock. */
208
209 pj_ice_strans_state state; /**< Session state. */
210 pj_ice_sess *ice; /**< ICE session. */
211 pj_time_val start_time;/**< Time when ICE was started */
212
213 unsigned comp_cnt; /**< Number of components. */
214 pj_ice_strans_comp **comp; /**< Components array. */
215
216 pj_pool_t *buf_pool; /**< Pool for buffers. */
217 unsigned num_buf; /**< Number of buffers. */
218 unsigned buf_idx; /**< Index of buffer. */
219 unsigned empty_idx; /**< Index of empty buffer. */
220 unsigned buf_size; /**< Buffer size. */
221 pending_send *send_buf; /**< Send buffers. */
222 pj_bool_t is_pending;/**< Any pending send? */
223
224 pj_timer_entry ka_timer; /**< STUN keep-alive timer. */
225
226 pj_bool_t destroy_req;/**< Destroy has been called? */
227 pj_bool_t cb_called; /**< Init error callback called?*/
228 pj_bool_t call_send_cb;/**< Need to call send cb? */
229
230 pj_bool_t rem_cand_end;/**< Trickle ICE: remote has
231 signalled end of candidate? */
232 pj_bool_t loc_cand_end;/**< Trickle ICE: local has
233 signalled end of candidate? */
234 };
235
236
237 /**
238 * This structure describe user data for STUN/TURN sockets of the
239 * ICE stream transport.
240 */
241 typedef struct sock_user_data
242 {
243 pj_ice_strans_comp *comp;
244 pj_uint8_t transport_id;
245
246 } sock_user_data;
247
248
249 /* Validate configuration */
pj_ice_strans_cfg_check_valid(const pj_ice_strans_cfg * cfg)250 static pj_status_t pj_ice_strans_cfg_check_valid(const pj_ice_strans_cfg *cfg)
251 {
252 pj_status_t status;
253
254 status = pj_stun_config_check_valid(&cfg->stun_cfg);
255 if (!status)
256 return status;
257
258 return PJ_SUCCESS;
259 }
260
261
262 /*
263 * Initialize ICE transport configuration with default values.
264 */
pj_ice_strans_cfg_default(pj_ice_strans_cfg * cfg)265 PJ_DEF(void) pj_ice_strans_cfg_default(pj_ice_strans_cfg *cfg)
266 {
267 pj_bzero(cfg, sizeof(*cfg));
268
269 cfg->af = pj_AF_INET();
270 pj_stun_config_init(&cfg->stun_cfg, NULL, 0, NULL, NULL);
271 pj_ice_strans_stun_cfg_default(&cfg->stun);
272 pj_ice_strans_turn_cfg_default(&cfg->turn);
273 pj_ice_sess_options_default(&cfg->opt);
274
275 cfg->num_send_buf = 4;
276 }
277
278
279 /*
280 * Initialize ICE STUN transport configuration with default values.
281 */
pj_ice_strans_stun_cfg_default(pj_ice_strans_stun_cfg * cfg)282 PJ_DEF(void) pj_ice_strans_stun_cfg_default(pj_ice_strans_stun_cfg *cfg)
283 {
284 pj_bzero(cfg, sizeof(*cfg));
285
286 cfg->af = pj_AF_INET();
287 cfg->port = PJ_STUN_PORT;
288 cfg->max_host_cands = 64;
289 cfg->ignore_stun_error = PJ_FALSE;
290 pj_stun_sock_cfg_default(&cfg->cfg);
291 }
292
293
294 /*
295 * Initialize ICE TURN transport configuration with default values.
296 */
pj_ice_strans_turn_cfg_default(pj_ice_strans_turn_cfg * cfg)297 PJ_DEF(void) pj_ice_strans_turn_cfg_default(pj_ice_strans_turn_cfg *cfg)
298 {
299 pj_bzero(cfg, sizeof(*cfg));
300
301 cfg->af = pj_AF_INET();
302 cfg->conn_type = PJ_TURN_TP_UDP;
303 pj_turn_alloc_param_default(&cfg->alloc_param);
304 pj_turn_sock_cfg_default(&cfg->cfg);
305 }
306
307
308 /*
309 * Copy configuration.
310 */
pj_ice_strans_cfg_copy(pj_pool_t * pool,pj_ice_strans_cfg * dst,const pj_ice_strans_cfg * src)311 PJ_DEF(void) pj_ice_strans_cfg_copy( pj_pool_t *pool,
312 pj_ice_strans_cfg *dst,
313 const pj_ice_strans_cfg *src)
314 {
315 unsigned i;
316
317 pj_memcpy(dst, src, sizeof(*src));
318
319 if (src->stun.server.slen)
320 pj_strdup(pool, &dst->stun.server, &src->stun.server);
321
322 for (i = 0; i < src->stun_tp_cnt; ++i) {
323 if (src->stun_tp[i].server.slen)
324 pj_strdup(pool, &dst->stun_tp[i].server,
325 &src->stun_tp[i].server);
326 }
327
328 if (src->turn.server.slen)
329 pj_strdup(pool, &dst->turn.server, &src->turn.server);
330 pj_stun_auth_cred_dup(pool, &dst->turn.auth_cred, &src->turn.auth_cred);
331
332 for (i = 0; i < src->turn_tp_cnt; ++i) {
333 if (src->turn_tp[i].server.slen)
334 pj_strdup(pool, &dst->turn_tp[i].server,
335 &src->turn_tp[i].server);
336 pj_stun_auth_cred_dup(pool, &dst->turn_tp[i].auth_cred,
337 &src->turn_tp[i].auth_cred);
338 }
339 }
340
341
342 /*
343 * Add or update TURN candidate.
344 */
add_update_turn(pj_ice_strans * ice_st,pj_ice_strans_comp * comp,unsigned idx,unsigned max_cand_cnt)345 static pj_status_t add_update_turn(pj_ice_strans *ice_st,
346 pj_ice_strans_comp *comp,
347 unsigned idx,
348 unsigned max_cand_cnt)
349 {
350 pj_ice_sess_cand *cand = NULL;
351 pj_ice_strans_turn_cfg *turn_cfg = &ice_st->cfg.turn_tp[idx];
352 pj_turn_sock_cfg *sock_cfg = &turn_cfg->cfg;
353 unsigned comp_idx = comp->comp_id - 1;
354 pj_turn_sock_cb turn_sock_cb;
355 sock_user_data *data;
356 unsigned i;
357 pj_bool_t new_cand = PJ_FALSE;
358 pj_uint8_t tp_id;
359 pj_status_t status;
360
361 /* Check if TURN transport is configured */
362 if (turn_cfg->server.slen == 0)
363 return PJ_SUCCESS;
364
365 /* Find relayed candidate in the component */
366 tp_id = CREATE_TP_ID(TP_TURN, idx);
367 for (i=0; i<comp->cand_cnt; ++i) {
368 if (comp->cand_list[i].transport_id == tp_id) {
369 cand = &comp->cand_list[i];
370 break;
371 }
372 }
373
374 /* If candidate is found, invalidate it first */
375 if (cand) {
376 cand->status = PJ_EPENDING;
377
378 /* Also if this component's default candidate is set to relay,
379 * move it temporarily to something else.
380 */
381 if ((int)comp->default_cand == cand - comp->cand_list) {
382 /* Init to something */
383 comp->default_cand = 0;
384 /* Use srflx candidate as the default, if any */
385 for (i=0; i<comp->cand_cnt; ++i) {
386 if (comp->cand_list[i].type == PJ_ICE_CAND_TYPE_SRFLX) {
387 comp->default_cand = i;
388 if (ice_st->cfg.af == pj_AF_UNSPEC() ||
389 comp->cand_list[i].base_addr.addr.sa_family ==
390 ice_st->cfg.af)
391 {
392 break;
393 }
394 }
395 }
396 }
397 }
398
399 /* Init TURN socket */
400 pj_bzero(&turn_sock_cb, sizeof(turn_sock_cb));
401 turn_sock_cb.on_rx_data = &turn_on_rx_data;
402 turn_sock_cb.on_data_sent = &turn_on_data_sent;
403 turn_sock_cb.on_state = &turn_on_state;
404
405 /* Override with component specific QoS settings, if any */
406 if (ice_st->cfg.comp[comp_idx].qos_type)
407 sock_cfg->qos_type = ice_st->cfg.comp[comp_idx].qos_type;
408 if (ice_st->cfg.comp[comp_idx].qos_params.flags)
409 pj_memcpy(&sock_cfg->qos_params,
410 &ice_st->cfg.comp[comp_idx].qos_params,
411 sizeof(sock_cfg->qos_params));
412
413 /* Override with component specific socket buffer size settings, if any */
414 if (ice_st->cfg.comp[comp_idx].so_rcvbuf_size > 0)
415 sock_cfg->so_rcvbuf_size = ice_st->cfg.comp[comp_idx].so_rcvbuf_size;
416 if (ice_st->cfg.comp[comp_idx].so_sndbuf_size > 0)
417 sock_cfg->so_sndbuf_size = ice_st->cfg.comp[comp_idx].so_sndbuf_size;
418
419 /* Add relayed candidate with pending status if there's no existing one */
420 if (cand == NULL) {
421 PJ_ASSERT_RETURN(max_cand_cnt > 0, PJ_ETOOSMALL);
422
423 cand = &comp->cand_list[comp->cand_cnt];
424 cand->type = PJ_ICE_CAND_TYPE_RELAYED;
425 cand->status = PJ_EPENDING;
426 cand->local_pref = (pj_uint16_t)(RELAY_PREF - idx);
427 cand->transport_id = tp_id;
428 cand->comp_id = (pj_uint8_t) comp->comp_id;
429 new_cand = PJ_TRUE;
430 }
431
432 /* Allocate and initialize TURN socket data */
433 data = PJ_POOL_ZALLOC_T(ice_st->pool, sock_user_data);
434 data->comp = comp;
435 data->transport_id = cand->transport_id;
436
437 /* Create the TURN transport */
438 status = pj_turn_sock_create(&ice_st->cfg.stun_cfg, turn_cfg->af,
439 turn_cfg->conn_type,
440 &turn_sock_cb, sock_cfg,
441 data, &comp->turn[idx].sock);
442 if (status != PJ_SUCCESS) {
443 return status;
444 }
445
446 if (new_cand) {
447 /* Commit the relayed candidate before pj_turn_sock_alloc(), as
448 * otherwise there can be race condition, please check
449 * https://github.com/pjsip/pjproject/pull/2525 for more info.
450 */
451 comp->cand_cnt++;
452 }
453
454 /* Add pending job */
455 ///sess_add_ref(ice_st);
456
457 /* Start allocation */
458 status=pj_turn_sock_alloc(comp->turn[idx].sock,
459 &turn_cfg->server,
460 turn_cfg->port,
461 ice_st->cfg.resolver,
462 &turn_cfg->auth_cred,
463 &turn_cfg->alloc_param);
464 if (status != PJ_SUCCESS) {
465 ///sess_dec_ref(ice_st);
466 cand->status = status;
467 return status;
468 }
469
470 PJ_LOG(4,(ice_st->obj_name,
471 "Comp %d/%d: TURN relay candidate (tpid=%d) "
472 "waiting for allocation",
473 comp->comp_id, comp->cand_cnt-1, cand->transport_id));
474
475 return PJ_SUCCESS;
476 }
477
ice_cand_equals(pj_ice_sess_cand * lcand,pj_ice_sess_cand * rcand)478 static pj_bool_t ice_cand_equals(pj_ice_sess_cand *lcand,
479 pj_ice_sess_cand *rcand)
480 {
481 if (lcand == NULL && rcand == NULL){
482 return PJ_TRUE;
483 }
484 if (lcand == NULL || rcand == NULL){
485 return PJ_FALSE;
486 }
487
488 if (lcand->type != rcand->type
489 || lcand->status != rcand->status
490 || lcand->comp_id != rcand->comp_id
491 || lcand->transport_id != rcand->transport_id
492 // local pref is no longer a constant, so it may be different
493 //|| lcand->local_pref != rcand->local_pref
494 || lcand->prio != rcand->prio
495 || pj_sockaddr_cmp(&lcand->addr, &rcand->addr) != 0
496 || pj_sockaddr_cmp(&lcand->base_addr, &rcand->base_addr) != 0)
497 {
498 return PJ_FALSE;
499 }
500
501 return PJ_TRUE;
502 }
503
504
add_stun_and_host(pj_ice_strans * ice_st,pj_ice_strans_comp * comp,unsigned idx,unsigned max_cand_cnt)505 static pj_status_t add_stun_and_host(pj_ice_strans *ice_st,
506 pj_ice_strans_comp *comp,
507 unsigned idx,
508 unsigned max_cand_cnt)
509 {
510 pj_ice_sess_cand *cand;
511 pj_ice_strans_stun_cfg *stun_cfg = &ice_st->cfg.stun_tp[idx];
512 pj_stun_sock_cfg *sock_cfg = &stun_cfg->cfg;
513 unsigned comp_idx = comp->comp_id - 1;
514 pj_stun_sock_cb stun_sock_cb;
515 sock_user_data *data;
516 pj_status_t status;
517
518 PJ_ASSERT_RETURN(max_cand_cnt > 0, PJ_ETOOSMALL);
519
520 /* Check if STUN transport or host candidate is configured */
521 if (stun_cfg->server.slen == 0 && stun_cfg->max_host_cands == 0)
522 return PJ_SUCCESS;
523
524 /* Initialize STUN socket callback */
525 pj_bzero(&stun_sock_cb, sizeof(stun_sock_cb));
526 stun_sock_cb.on_rx_data = &stun_on_rx_data;
527 stun_sock_cb.on_status = &stun_on_status;
528 stun_sock_cb.on_data_sent = &stun_on_data_sent;
529
530 /* Override component specific QoS settings, if any */
531 if (ice_st->cfg.comp[comp_idx].qos_type) {
532 sock_cfg->qos_type = ice_st->cfg.comp[comp_idx].qos_type;
533 }
534 if (ice_st->cfg.comp[comp_idx].qos_params.flags) {
535 pj_memcpy(&sock_cfg->qos_params,
536 &ice_st->cfg.comp[comp_idx].qos_params,
537 sizeof(sock_cfg->qos_params));
538 }
539
540 /* Override component specific socket buffer size settings, if any */
541 if (ice_st->cfg.comp[comp_idx].so_rcvbuf_size > 0) {
542 sock_cfg->so_rcvbuf_size = ice_st->cfg.comp[comp_idx].so_rcvbuf_size;
543 }
544 if (ice_st->cfg.comp[comp_idx].so_sndbuf_size > 0) {
545 sock_cfg->so_sndbuf_size = ice_st->cfg.comp[comp_idx].so_sndbuf_size;
546 }
547
548 /* Prepare srflx candidate with pending status. */
549 cand = &comp->cand_list[comp->cand_cnt];
550 cand->type = PJ_ICE_CAND_TYPE_SRFLX;
551 cand->status = PJ_EPENDING;
552 cand->local_pref = (pj_uint16_t)(SRFLX_PREF - idx);
553 cand->transport_id = CREATE_TP_ID(TP_STUN, idx);
554 cand->comp_id = (pj_uint8_t) comp->comp_id;
555
556 /* Allocate and initialize STUN socket data */
557 data = PJ_POOL_ZALLOC_T(ice_st->pool, sock_user_data);
558 data->comp = comp;
559 data->transport_id = cand->transport_id;
560
561 /* Create the STUN transport */
562 status = pj_stun_sock_create(&ice_st->cfg.stun_cfg, NULL,
563 stun_cfg->af, &stun_sock_cb,
564 sock_cfg, data, &comp->stun[idx].sock);
565 if (status != PJ_SUCCESS)
566 return status;
567
568 /* Start STUN Binding resolution and add srflx candidate only if server
569 * is set. When any error occur during STUN Binding resolution, let's
570 * just skip it and generate host candidates.
571 */
572 while (stun_cfg->server.slen) {
573 pj_stun_sock_info stun_sock_info;
574
575 /* Add pending job */
576 ///sess_add_ref(ice_st);
577
578 PJ_LOG(4,(ice_st->obj_name,
579 "Comp %d: srflx candidate (tpid=%d) starts "
580 "Binding discovery",
581 comp->comp_id, cand->transport_id));
582
583 pj_log_push_indent();
584
585 /* Start Binding resolution */
586 status = pj_stun_sock_start(comp->stun[idx].sock, &stun_cfg->server,
587 stun_cfg->port, ice_st->cfg.resolver);
588 if (status != PJ_SUCCESS) {
589 ///sess_dec_ref(ice_st);
590 PJ_PERROR(5,(ice_st->obj_name, status,
591 "Comp %d: srflx candidate (tpid=%d) failed in "
592 "pj_stun_sock_start()",
593 comp->comp_id, cand->transport_id));
594 pj_log_pop_indent();
595 break;
596 }
597
598 /* Enumerate addresses */
599 status = pj_stun_sock_get_info(comp->stun[idx].sock, &stun_sock_info);
600 if (status != PJ_SUCCESS) {
601 ///sess_dec_ref(ice_st);
602 PJ_PERROR(5,(ice_st->obj_name, status,
603 "Comp %d: srflx candidate (tpid=%d) failed in "
604 "pj_stun_sock_get_info()",
605 comp->comp_id, cand->transport_id));
606 pj_log_pop_indent();
607 break;
608 }
609
610 /* Update and commit the srflx candidate. */
611 pj_sockaddr_cp(&cand->base_addr, &stun_sock_info.aliases[0]);
612 pj_sockaddr_cp(&cand->rel_addr, &cand->base_addr);
613 pj_ice_calc_foundation(ice_st->pool, &cand->foundation,
614 cand->type, &cand->base_addr);
615 comp->cand_cnt++;
616 max_cand_cnt--;
617
618 /* Set default candidate to srflx */
619 if (comp->cand_list[comp->default_cand].type != PJ_ICE_CAND_TYPE_SRFLX
620 || (ice_st->cfg.af != pj_AF_UNSPEC() &&
621 comp->cand_list[comp->default_cand].base_addr.addr.sa_family
622 != ice_st->cfg.af))
623 {
624 comp->default_cand = (unsigned)(cand - comp->cand_list);
625 }
626
627 pj_log_pop_indent();
628
629 /* Not really a loop, just trying to avoid complex 'if' blocks */
630 break;
631 }
632
633 /* Add local addresses to host candidates, unless max_host_cands
634 * is set to zero.
635 */
636 if (stun_cfg->max_host_cands) {
637 pj_stun_sock_info stun_sock_info;
638 unsigned i, cand_cnt = 0;
639
640 /* Enumerate addresses */
641 status = pj_stun_sock_get_info(comp->stun[idx].sock, &stun_sock_info);
642 if (status != PJ_SUCCESS) {
643 PJ_PERROR(4,(ice_st->obj_name, status,
644 "Failed in querying STUN socket info"));
645 return status;
646 }
647
648 for (i = 0; i < stun_sock_info.alias_cnt &&
649 cand_cnt < stun_cfg->max_host_cands; ++i)
650 {
651 unsigned j;
652 pj_bool_t cand_duplicate = PJ_FALSE;
653 char addrinfo[PJ_INET6_ADDRSTRLEN+10];
654 const pj_sockaddr *addr = &stun_sock_info.aliases[i];
655
656 if (max_cand_cnt==0) {
657 PJ_LOG(4,(ice_st->obj_name, "Too many host candidates"));
658 break;
659 }
660
661 /* Ignore loopback addresses if cfg->stun.loop_addr is unset */
662 if (stun_cfg->loop_addr==PJ_FALSE) {
663 if (stun_cfg->af == pj_AF_INET() &&
664 (pj_ntohl(addr->ipv4.sin_addr.s_addr)>>24)==127)
665 {
666 continue;
667 }
668 else if (stun_cfg->af == pj_AF_INET6()) {
669 pj_in6_addr in6addr = {{{0}}};
670 in6addr.s6_addr[15] = 1;
671 if (pj_memcmp(&in6addr, &addr->ipv6.sin6_addr,
672 sizeof(in6addr))==0)
673 {
674 continue;
675 }
676 }
677 }
678
679 /* Ignore IPv6 link-local address, unless it is the default
680 * address (first alias).
681 */
682 if (stun_cfg->af == pj_AF_INET6() && i != 0) {
683 const pj_in6_addr *a = &addr->ipv6.sin6_addr;
684 if (a->s6_addr[0] == 0xFE && (a->s6_addr[1] & 0xC0) == 0x80)
685 continue;
686 }
687
688 cand = &comp->cand_list[comp->cand_cnt];
689
690 cand->type = PJ_ICE_CAND_TYPE_HOST;
691 cand->status = PJ_SUCCESS;
692 cand->local_pref = (pj_uint16_t)(HOST_PREF - cand_cnt);
693 cand->transport_id = CREATE_TP_ID(TP_STUN, idx);
694 cand->comp_id = (pj_uint8_t) comp->comp_id;
695 pj_sockaddr_cp(&cand->addr, addr);
696 pj_sockaddr_cp(&cand->base_addr, addr);
697 pj_bzero(&cand->rel_addr, sizeof(cand->rel_addr));
698
699 /* Check if not already in list */
700 for (j=0; j<comp->cand_cnt; j++) {
701 if (ice_cand_equals(cand, &comp->cand_list[j])) {
702 cand_duplicate = PJ_TRUE;
703 break;
704 }
705 }
706
707 if (cand_duplicate) {
708 PJ_LOG(4, (ice_st->obj_name,
709 "Comp %d: host candidate %s (tpid=%d) is a duplicate",
710 comp->comp_id, pj_sockaddr_print(&cand->addr, addrinfo,
711 sizeof(addrinfo), 3), cand->transport_id));
712
713 pj_bzero(&cand->addr, sizeof(cand->addr));
714 pj_bzero(&cand->base_addr, sizeof(cand->base_addr));
715 continue;
716 } else {
717 comp->cand_cnt+=1;
718 cand_cnt++;
719 max_cand_cnt--;
720 }
721
722 pj_ice_calc_foundation(ice_st->pool, &cand->foundation,
723 cand->type, &cand->base_addr);
724
725 /* Set default candidate with the preferred default
726 * address family
727 */
728 if (comp->ice_st->cfg.af != pj_AF_UNSPEC() &&
729 addr->addr.sa_family == comp->ice_st->cfg.af &&
730 comp->cand_list[comp->default_cand].base_addr.addr.sa_family !=
731 ice_st->cfg.af)
732 {
733 comp->default_cand = (unsigned)(cand - comp->cand_list);
734 }
735
736 PJ_LOG(4,(ice_st->obj_name,
737 "Comp %d/%d: host candidate %s (tpid=%d) added",
738 comp->comp_id, comp->cand_cnt-1,
739 pj_sockaddr_print(&cand->addr, addrinfo,
740 sizeof(addrinfo), 3),
741 cand->transport_id));
742 }
743 }
744
745 return status;
746 }
747
748
749 /*
750 * Create the component.
751 */
create_comp(pj_ice_strans * ice_st,unsigned comp_id)752 static pj_status_t create_comp(pj_ice_strans *ice_st, unsigned comp_id)
753 {
754 pj_ice_strans_comp *comp = NULL;
755 unsigned i;
756 pj_status_t status;
757
758 /* Verify arguments */
759 PJ_ASSERT_RETURN(ice_st && comp_id, PJ_EINVAL);
760
761 /* Check that component ID present */
762 PJ_ASSERT_RETURN(comp_id <= ice_st->comp_cnt, PJNATH_EICEINCOMPID);
763
764 /* Create component */
765 comp = PJ_POOL_ZALLOC_T(ice_st->pool, pj_ice_strans_comp);
766 comp->ice_st = ice_st;
767 comp->comp_id = comp_id;
768 comp->creating = PJ_TRUE;
769
770 ice_st->comp[comp_id-1] = comp;
771
772 /* Initialize default candidate */
773 comp->default_cand = 0;
774
775 /* Create STUN transport if configured */
776 for (i=0; i<ice_st->cfg.stun_tp_cnt; ++i) {
777 unsigned max_cand_cnt = PJ_ICE_ST_MAX_CAND - comp->cand_cnt -
778 ice_st->cfg.turn_tp_cnt;
779
780 status = PJ_ETOOSMALL;
781
782 if ((max_cand_cnt > 0) && (max_cand_cnt <= PJ_ICE_ST_MAX_CAND))
783 status = add_stun_and_host(ice_st, comp, i, max_cand_cnt);
784
785 if (status != PJ_SUCCESS) {
786 PJ_PERROR(3,(ice_st->obj_name, status,
787 "Failed creating STUN transport #%d for comp %d",
788 i, comp->comp_id));
789 //return status;
790 }
791 }
792
793 /* Create TURN relay if configured. */
794 for (i=0; i<ice_st->cfg.turn_tp_cnt; ++i) {
795 unsigned max_cand_cnt = PJ_ICE_ST_MAX_CAND - comp->cand_cnt;
796
797 status = PJ_ETOOSMALL;
798
799 if ((max_cand_cnt > 0) && (max_cand_cnt <= PJ_ICE_ST_MAX_CAND))
800 status = add_update_turn(ice_st, comp, i, max_cand_cnt);
801
802 if (status != PJ_SUCCESS) {
803 PJ_PERROR(3,(ice_st->obj_name, status,
804 "Failed creating TURN transport #%d for comp %d",
805 i, comp->comp_id));
806
807 //return status;
808 } else if (max_cand_cnt > 0) {
809 max_cand_cnt = PJ_ICE_ST_MAX_CAND - comp->cand_cnt;
810 }
811 }
812
813 /* Done creating all the candidates */
814 comp->creating = PJ_FALSE;
815
816 /* It's possible that we end up without any candidates */
817 if (comp->cand_cnt == 0) {
818 PJ_LOG(4,(ice_st->obj_name,
819 "Error: no candidate is created due to settings"));
820 return PJ_EINVAL;
821 }
822
823 return PJ_SUCCESS;
824 }
825
alloc_send_buf(pj_ice_strans * ice_st,unsigned buf_size)826 static pj_status_t alloc_send_buf(pj_ice_strans *ice_st, unsigned buf_size)
827 {
828 if (buf_size > ice_st->buf_size) {
829 unsigned i;
830
831 if (ice_st->is_pending) {
832 /* The current buffer is insufficient, but still currently used.*/
833 return PJ_EBUSY;
834 }
835
836 pj_pool_safe_release(&ice_st->buf_pool);
837
838 ice_st->buf_pool = pj_pool_create(ice_st->pf, "ice_buf",
839 (buf_size + sizeof(pending_send)) *
840 ice_st->num_buf, 512, NULL);
841 if (!ice_st->buf_pool)
842 return PJ_ENOMEM;
843
844 ice_st->buf_size = buf_size;
845 ice_st->send_buf = pj_pool_calloc(ice_st->buf_pool, ice_st->num_buf,
846 sizeof(pending_send));
847 for (i = 0; i < ice_st->num_buf; i++) {
848 ice_st->send_buf[i].buffer = pj_pool_alloc(ice_st->buf_pool,
849 buf_size);
850 }
851 ice_st->buf_idx = ice_st->empty_idx = 0;
852 }
853
854 return PJ_SUCCESS;
855 }
856
857 /*
858 * Create ICE stream transport
859 */
pj_ice_strans_create(const char * name,const pj_ice_strans_cfg * cfg,unsigned comp_cnt,void * user_data,const pj_ice_strans_cb * cb,pj_ice_strans ** p_ice_st)860 PJ_DEF(pj_status_t) pj_ice_strans_create( const char *name,
861 const pj_ice_strans_cfg *cfg,
862 unsigned comp_cnt,
863 void *user_data,
864 const pj_ice_strans_cb *cb,
865 pj_ice_strans **p_ice_st)
866 {
867 pj_pool_t *pool;
868 pj_ice_strans *ice_st;
869 unsigned i;
870 pj_status_t status;
871
872 status = pj_ice_strans_cfg_check_valid(cfg);
873 if (status != PJ_SUCCESS)
874 return status;
875
876 PJ_ASSERT_RETURN(comp_cnt && cb && p_ice_st &&
877 comp_cnt <= PJ_ICE_MAX_COMP , PJ_EINVAL);
878
879 if (name == NULL)
880 name = "ice%p";
881
882 pool = pj_pool_create(cfg->stun_cfg.pf, name, PJNATH_POOL_LEN_ICE_STRANS,
883 PJNATH_POOL_INC_ICE_STRANS, NULL);
884 ice_st = PJ_POOL_ZALLOC_T(pool, pj_ice_strans);
885 ice_st->pool = pool;
886 ice_st->pf = cfg->stun_cfg.pf;
887 ice_st->obj_name = pool->obj_name;
888 ice_st->user_data = user_data;
889
890 PJ_LOG(4,(ice_st->obj_name,
891 "Creating ICE stream transport with %d component(s)",
892 comp_cnt));
893 pj_log_push_indent();
894
895 status = pj_grp_lock_create(pool, NULL, &ice_st->grp_lock);
896 if (status != PJ_SUCCESS) {
897 pj_pool_release(pool);
898 pj_log_pop_indent();
899 return status;
900 }
901
902 /* Allocate send buffer */
903 ice_st->num_buf = cfg->num_send_buf;
904 status = alloc_send_buf(ice_st, cfg->send_buf_size);
905 if (status != PJ_SUCCESS) {
906 destroy_ice_st(ice_st);
907 pj_log_pop_indent();
908 return status;
909 }
910
911 pj_grp_lock_add_ref(ice_st->grp_lock);
912 pj_grp_lock_add_handler(ice_st->grp_lock, pool, ice_st,
913 &ice_st_on_destroy);
914
915 pj_ice_strans_cfg_copy(pool, &ice_st->cfg, cfg);
916
917 /* To maintain backward compatibility, check if old/deprecated setting is set
918 * and the new setting is not, copy the value to the new setting.
919 */
920 if (cfg->stun_tp_cnt == 0 &&
921 (cfg->stun.server.slen || cfg->stun.max_host_cands))
922 {
923 ice_st->cfg.stun_tp_cnt = 1;
924 ice_st->cfg.stun_tp[0] = ice_st->cfg.stun;
925 }
926 if (cfg->turn_tp_cnt == 0 && cfg->turn.server.slen) {
927 ice_st->cfg.turn_tp_cnt = 1;
928 ice_st->cfg.turn_tp[0] = ice_st->cfg.turn;
929 }
930
931 for (i=0; i<ice_st->cfg.stun_tp_cnt; ++i)
932 ice_st->cfg.stun_tp[i].cfg.grp_lock = ice_st->grp_lock;
933 for (i=0; i<ice_st->cfg.turn_tp_cnt; ++i)
934 ice_st->cfg.turn_tp[i].cfg.grp_lock = ice_st->grp_lock;
935 pj_memcpy(&ice_st->cb, cb, sizeof(*cb));
936
937 ice_st->comp_cnt = comp_cnt;
938 ice_st->comp = (pj_ice_strans_comp**)
939 pj_pool_calloc(pool, comp_cnt, sizeof(pj_ice_strans_comp*));
940
941 /* Move state to candidate gathering */
942 ice_st->state = PJ_ICE_STRANS_STATE_INIT;
943
944 /* Acquire initialization mutex to prevent callback to be
945 * called before we finish initialization.
946 */
947 pj_grp_lock_acquire(ice_st->grp_lock);
948
949 for (i=0; i<comp_cnt; ++i) {
950 status = create_comp(ice_st, i+1);
951 if (status != PJ_SUCCESS) {
952 pj_grp_lock_release(ice_st->grp_lock);
953 destroy_ice_st(ice_st);
954 pj_log_pop_indent();
955 return status;
956 }
957 }
958
959 /* Done with initialization */
960 pj_grp_lock_release(ice_st->grp_lock);
961
962 PJ_LOG(4,(ice_st->obj_name, "ICE stream transport %p created", ice_st));
963
964 *p_ice_st = ice_st;
965
966 /* Check if all candidates are ready (this may call callback) */
967 sess_init_update(ice_st);
968
969 /* If ICE init done, notify app about end of candidate gathering via
970 * on_new_candidate() callback.
971 */
972 if (ice_st->state==PJ_ICE_STRANS_STATE_READY &&
973 ice_st->cb.on_new_candidate)
974 {
975 (*ice_st->cb.on_new_candidate)(ice_st, NULL, PJ_TRUE);
976 }
977
978 pj_log_pop_indent();
979
980 return PJ_SUCCESS;
981 }
982
983 /* REALLY destroy ICE */
ice_st_on_destroy(void * obj)984 static void ice_st_on_destroy(void *obj)
985 {
986 pj_ice_strans *ice_st = (pj_ice_strans*)obj;
987
988 PJ_LOG(4,(ice_st->obj_name, "ICE stream transport %p destroyed", obj));
989
990 /* Done */
991 pj_pool_safe_release(&ice_st->buf_pool);
992 pj_pool_safe_release(&ice_st->pool);
993 }
994
995 /* Destroy ICE */
destroy_ice_st(pj_ice_strans * ice_st)996 static void destroy_ice_st(pj_ice_strans *ice_st)
997 {
998 unsigned i;
999
1000 PJ_LOG(5,(ice_st->obj_name, "ICE stream transport %p destroy request..",
1001 ice_st));
1002 pj_log_push_indent();
1003
1004 /* Reset callback and user data */
1005 pj_bzero(&ice_st->cb, sizeof(ice_st->cb));
1006 ice_st->user_data = NULL;
1007
1008 pj_grp_lock_acquire(ice_st->grp_lock);
1009
1010 if (ice_st->destroy_req) {
1011 pj_grp_lock_release(ice_st->grp_lock);
1012 return;
1013 }
1014
1015 ice_st->destroy_req = PJ_TRUE;
1016
1017 /* Destroy ICE if we have ICE */
1018 if (ice_st->ice) {
1019 pj_ice_sess_destroy(ice_st->ice);
1020 ice_st->ice = NULL;
1021 }
1022
1023 /* Destroy all components */
1024 for (i=0; i<ice_st->comp_cnt; ++i) {
1025 if (ice_st->comp[i]) {
1026 pj_ice_strans_comp *comp = ice_st->comp[i];
1027 unsigned j;
1028 for (j = 0; j < ice_st->cfg.stun_tp_cnt; ++j) {
1029 if (comp->stun[j].sock) {
1030 pj_stun_sock_destroy(comp->stun[j].sock);
1031 comp->stun[j].sock = NULL;
1032 }
1033 }
1034 for (j = 0; j < ice_st->cfg.turn_tp_cnt; ++j) {
1035 if (comp->turn[j].sock) {
1036 pj_turn_sock_destroy(comp->turn[j].sock);
1037 comp->turn[j].sock = NULL;
1038 }
1039 }
1040 }
1041 }
1042
1043 pj_grp_lock_dec_ref(ice_st->grp_lock);
1044 pj_grp_lock_release(ice_st->grp_lock);
1045
1046 pj_log_pop_indent();
1047 }
1048
1049 /* Get ICE session state. */
pj_ice_strans_get_state(pj_ice_strans * ice_st)1050 PJ_DEF(pj_ice_strans_state) pj_ice_strans_get_state(pj_ice_strans *ice_st)
1051 {
1052 return ice_st->state;
1053 }
1054
1055 /* State string */
pj_ice_strans_state_name(pj_ice_strans_state state)1056 PJ_DEF(const char*) pj_ice_strans_state_name(pj_ice_strans_state state)
1057 {
1058 const char *names[] = {
1059 "Null",
1060 "Candidate Gathering",
1061 "Candidate Gathering Complete",
1062 "Session Initialized",
1063 "Negotiation In Progress",
1064 "Negotiation Success",
1065 "Negotiation Failed"
1066 };
1067
1068 PJ_ASSERT_RETURN(state <= PJ_ICE_STRANS_STATE_FAILED, "???");
1069 return names[state];
1070 }
1071
1072 /* Notification about failure */
sess_fail(pj_ice_strans * ice_st,pj_ice_strans_op op,const char * title,pj_status_t status)1073 static void sess_fail(pj_ice_strans *ice_st, pj_ice_strans_op op,
1074 const char *title, pj_status_t status)
1075 {
1076 PJ_PERROR(4,(ice_st->obj_name, status, title));
1077
1078 pj_log_push_indent();
1079
1080 if (op==PJ_ICE_STRANS_OP_INIT && ice_st->cb_called) {
1081 pj_log_pop_indent();
1082 return;
1083 }
1084
1085 ice_st->cb_called = PJ_TRUE;
1086
1087 if (ice_st->cb.on_ice_complete)
1088 (*ice_st->cb.on_ice_complete)(ice_st, op, status);
1089
1090 pj_log_pop_indent();
1091 }
1092
1093 /* Update initialization status */
sess_init_update(pj_ice_strans * ice_st)1094 static void sess_init_update(pj_ice_strans *ice_st)
1095 {
1096 unsigned i;
1097 pj_status_t status = PJ_EUNKNOWN;
1098
1099 /* Ignore if ICE is destroying or init callback has been called */
1100 if (ice_st->destroy_req || ice_st->cb_called)
1101 return;
1102
1103 /* Notify application when all candidates have been gathered */
1104 for (i=0; i<ice_st->comp_cnt; ++i) {
1105 unsigned j;
1106 pj_ice_strans_comp *comp = ice_st->comp[i];
1107
1108 /* This function can be called when all components or candidates
1109 * have not been created.
1110 */
1111 if (!comp || comp->creating) {
1112 PJ_LOG(5, (ice_st->obj_name, "ICE init update: creating comp %d",
1113 (comp?comp->comp_id:(i+1)) ));
1114 return;
1115 }
1116
1117 status = PJ_EUNKNOWN;
1118 for (j=0; j<comp->cand_cnt; ++j) {
1119 pj_ice_sess_cand *cand = &comp->cand_list[j];
1120
1121 if (cand->status == PJ_EPENDING) {
1122 PJ_LOG(5, (ice_st->obj_name, "ICE init update: "
1123 "comp %d/%d[%s] is pending",
1124 comp->comp_id, j,
1125 pj_ice_get_cand_type_name(cand->type)));
1126 return;
1127 }
1128
1129 if (status == PJ_EUNKNOWN) {
1130 status = cand->status;
1131 } else {
1132 /* We only need one successful candidate. */
1133 if (cand->status == PJ_SUCCESS)
1134 status = PJ_SUCCESS;
1135 }
1136 }
1137
1138 if (status != PJ_SUCCESS)
1139 break;
1140 }
1141
1142 /* All candidates have been gathered or there's no successful
1143 * candidate for a component.
1144 */
1145 ice_st->cb_called = PJ_TRUE;
1146 ice_st->state = PJ_ICE_STRANS_STATE_READY;
1147 if (ice_st->cb.on_ice_complete)
1148 (*ice_st->cb.on_ice_complete)(ice_st, PJ_ICE_STRANS_OP_INIT,
1149 status);
1150
1151 /* Tell ICE session that trickling is done */
1152 ice_st->loc_cand_end = PJ_TRUE;
1153 if (ice_st->ice && ice_st->ice->is_trickling && ice_st->rem_cand_end) {
1154 pj_ice_sess_update_check_list(ice_st->ice, NULL, NULL, 0, NULL,
1155 PJ_TRUE);
1156 }
1157 }
1158
1159 /*
1160 * Destroy ICE stream transport.
1161 */
pj_ice_strans_destroy(pj_ice_strans * ice_st)1162 PJ_DEF(pj_status_t) pj_ice_strans_destroy(pj_ice_strans *ice_st)
1163 {
1164 destroy_ice_st(ice_st);
1165 return PJ_SUCCESS;
1166 }
1167
1168
1169 /*
1170 * Get user data
1171 */
pj_ice_strans_get_user_data(pj_ice_strans * ice_st)1172 PJ_DEF(void*) pj_ice_strans_get_user_data(pj_ice_strans *ice_st)
1173 {
1174 PJ_ASSERT_RETURN(ice_st, NULL);
1175 return ice_st->user_data;
1176 }
1177
1178
1179 /*
1180 * Get the value of various options of the ICE stream transport.
1181 */
pj_ice_strans_get_options(pj_ice_strans * ice_st,pj_ice_sess_options * opt)1182 PJ_DEF(pj_status_t) pj_ice_strans_get_options( pj_ice_strans *ice_st,
1183 pj_ice_sess_options *opt)
1184 {
1185 PJ_ASSERT_RETURN(ice_st && opt, PJ_EINVAL);
1186 pj_memcpy(opt, &ice_st->cfg.opt, sizeof(*opt));
1187 return PJ_SUCCESS;
1188 }
1189
1190 /*
1191 * Specify various options for this ICE stream transport.
1192 */
pj_ice_strans_set_options(pj_ice_strans * ice_st,const pj_ice_sess_options * opt)1193 PJ_DEF(pj_status_t) pj_ice_strans_set_options(pj_ice_strans *ice_st,
1194 const pj_ice_sess_options *opt)
1195 {
1196 PJ_ASSERT_RETURN(ice_st && opt, PJ_EINVAL);
1197 pj_memcpy(&ice_st->cfg.opt, opt, sizeof(*opt));
1198 if (ice_st->ice)
1199 pj_ice_sess_set_options(ice_st->ice, &ice_st->cfg.opt);
1200 return PJ_SUCCESS;
1201 }
1202
1203 /*
1204 * Update number of components of the ICE stream transport.
1205 */
pj_ice_strans_update_comp_cnt(pj_ice_strans * ice_st,unsigned comp_cnt)1206 PJ_DEF(pj_status_t) pj_ice_strans_update_comp_cnt( pj_ice_strans *ice_st,
1207 unsigned comp_cnt)
1208 {
1209 unsigned i;
1210
1211 PJ_ASSERT_RETURN(ice_st && comp_cnt < ice_st->comp_cnt, PJ_EINVAL);
1212 PJ_ASSERT_RETURN(ice_st->ice == NULL, PJ_EINVALIDOP);
1213
1214 pj_grp_lock_acquire(ice_st->grp_lock);
1215
1216 for (i=comp_cnt; i<ice_st->comp_cnt; ++i) {
1217 pj_ice_strans_comp *comp = ice_st->comp[i];
1218 unsigned j;
1219
1220 /* Destroy the component */
1221 for (j = 0; j < ice_st->cfg.stun_tp_cnt; ++j) {
1222 if (comp->stun[j].sock) {
1223 pj_stun_sock_destroy(comp->stun[j].sock);
1224 comp->stun[j].sock = NULL;
1225 }
1226 }
1227 for (j = 0; j < ice_st->cfg.turn_tp_cnt; ++j) {
1228 if (comp->turn[j].sock) {
1229 pj_turn_sock_destroy(comp->turn[j].sock);
1230 comp->turn[j].sock = NULL;
1231 }
1232 }
1233 comp->cand_cnt = 0;
1234 ice_st->comp[i] = NULL;
1235 }
1236 ice_st->comp_cnt = comp_cnt;
1237 pj_grp_lock_release(ice_st->grp_lock);
1238
1239 PJ_LOG(4,(ice_st->obj_name,
1240 "Updated ICE stream transport components number to %d",
1241 comp_cnt));
1242
1243 return PJ_SUCCESS;
1244 }
1245
1246 /**
1247 * Get the group lock for this ICE stream transport.
1248 */
pj_ice_strans_get_grp_lock(pj_ice_strans * ice_st)1249 PJ_DEF(pj_grp_lock_t *) pj_ice_strans_get_grp_lock(pj_ice_strans *ice_st)
1250 {
1251 PJ_ASSERT_RETURN(ice_st, NULL);
1252 return ice_st->grp_lock;
1253 }
1254
1255 /*
1256 * Create ICE!
1257 */
pj_ice_strans_init_ice(pj_ice_strans * ice_st,pj_ice_sess_role role,const pj_str_t * local_ufrag,const pj_str_t * local_passwd)1258 PJ_DEF(pj_status_t) pj_ice_strans_init_ice(pj_ice_strans *ice_st,
1259 pj_ice_sess_role role,
1260 const pj_str_t *local_ufrag,
1261 const pj_str_t *local_passwd)
1262 {
1263 pj_status_t status;
1264 unsigned i;
1265 pj_ice_sess_cb ice_cb;
1266 //const pj_uint8_t srflx_prio[4] = { 100, 126, 110, 0 };
1267
1268 /* Check arguments */
1269 PJ_ASSERT_RETURN(ice_st, PJ_EINVAL);
1270 /* Must not have ICE */
1271 PJ_ASSERT_RETURN(ice_st->ice == NULL, PJ_EINVALIDOP);
1272 /* Components must have been created */
1273 PJ_ASSERT_RETURN(ice_st->comp[0] != NULL, PJ_EINVALIDOP);
1274
1275 /* Init callback */
1276 pj_bzero(&ice_cb, sizeof(ice_cb));
1277 ice_cb.on_valid_pair = &on_valid_pair;
1278 ice_cb.on_ice_complete = &on_ice_complete;
1279 ice_cb.on_rx_data = &ice_rx_data;
1280 ice_cb.on_tx_pkt = &ice_tx_pkt;
1281
1282 /* Create! */
1283 status = pj_ice_sess_create(&ice_st->cfg.stun_cfg, ice_st->obj_name, role,
1284 ice_st->comp_cnt, &ice_cb,
1285 local_ufrag, local_passwd,
1286 ice_st->grp_lock,
1287 &ice_st->ice);
1288 if (status != PJ_SUCCESS)
1289 return status;
1290
1291 /* Associate user data */
1292 ice_st->ice->user_data = (void*)ice_st;
1293
1294 /* Set options */
1295 pj_ice_sess_set_options(ice_st->ice, &ice_st->cfg.opt);
1296
1297 /* If default candidate for components are SRFLX one, upload a custom
1298 * type priority to ICE session so that SRFLX candidates will get
1299 * checked first.
1300 */
1301 if (ice_st->comp[0]->cand_list[ice_st->comp[0]->default_cand].type
1302 == PJ_ICE_CAND_TYPE_SRFLX)
1303 {
1304 pj_ice_sess_set_prefs(ice_st->ice, srflx_pref_table);
1305 }
1306
1307 /* Add components/candidates */
1308 for (i=0; i<ice_st->comp_cnt; ++i) {
1309 unsigned j;
1310 pj_ice_strans_comp *comp = ice_st->comp[i];
1311
1312 /* Re-enable logging for Send/Data indications */
1313 if (ice_st->cfg.turn_tp_cnt) {
1314 PJ_LOG(5,(ice_st->obj_name,
1315 "Enabling STUN Indication logging for "
1316 "component %d", i+1));
1317 }
1318 for (j = 0; j < ice_st->cfg.turn_tp_cnt; ++j) {
1319 if (comp->turn[j].sock) {
1320 pj_turn_sock_set_log(comp->turn[j].sock, 0xFFFF);
1321 comp->turn[j].log_off = PJ_FALSE;
1322 }
1323 }
1324
1325 for (j=0; j<comp->cand_cnt; ++j) {
1326 pj_ice_sess_cand *cand = &comp->cand_list[j];
1327 unsigned ice_cand_id;
1328
1329 /* Skip if candidate is not ready */
1330 if (cand->status != PJ_SUCCESS) {
1331 PJ_LOG(5,(ice_st->obj_name,
1332 "Candidate %d of comp %d is not added (pending)",
1333 j, i));
1334 continue;
1335 }
1336
1337 /* Must have address */
1338 pj_assert(pj_sockaddr_has_addr(&cand->addr));
1339
1340 /* Skip if we are mapped to IPv4 address and this candidate
1341 * is not IPv4.
1342 */
1343 if (comp->ipv4_mapped &&
1344 cand->addr.addr.sa_family != pj_AF_INET())
1345 {
1346 continue;
1347 }
1348
1349 /* Add the candidate */
1350 status = pj_ice_sess_add_cand(ice_st->ice, comp->comp_id,
1351 cand->transport_id, cand->type,
1352 cand->local_pref,
1353 &cand->foundation, &cand->addr,
1354 &cand->base_addr, &cand->rel_addr,
1355 pj_sockaddr_get_len(&cand->addr),
1356 (unsigned*)&ice_cand_id);
1357 if (status != PJ_SUCCESS)
1358 goto on_error;
1359 }
1360 }
1361
1362 /* ICE session is ready for negotiation */
1363 ice_st->state = PJ_ICE_STRANS_STATE_SESS_READY;
1364
1365 return PJ_SUCCESS;
1366
1367 on_error:
1368 pj_ice_strans_stop_ice(ice_st);
1369 return status;
1370 }
1371
1372 /*
1373 * Check if the ICE stream transport has the ICE session created.
1374 */
pj_ice_strans_has_sess(pj_ice_strans * ice_st)1375 PJ_DEF(pj_bool_t) pj_ice_strans_has_sess(pj_ice_strans *ice_st)
1376 {
1377 PJ_ASSERT_RETURN(ice_st, PJ_FALSE);
1378 return ice_st->ice != NULL;
1379 }
1380
1381 /*
1382 * Check if ICE negotiation is still running.
1383 */
pj_ice_strans_sess_is_running(pj_ice_strans * ice_st)1384 PJ_DEF(pj_bool_t) pj_ice_strans_sess_is_running(pj_ice_strans *ice_st)
1385 {
1386 // Trickle ICE can start ICE before remote candidate list is received
1387 return ice_st && ice_st->ice && /* ice_st->ice->rcand_cnt && */
1388 ice_st->ice->clist.state == PJ_ICE_SESS_CHECKLIST_ST_RUNNING &&
1389 !pj_ice_strans_sess_is_complete(ice_st);
1390 }
1391
1392
1393 /*
1394 * Check if ICE negotiation has completed.
1395 */
pj_ice_strans_sess_is_complete(pj_ice_strans * ice_st)1396 PJ_DEF(pj_bool_t) pj_ice_strans_sess_is_complete(pj_ice_strans *ice_st)
1397 {
1398 return ice_st && ice_st->ice && ice_st->ice->is_complete;
1399 }
1400
1401
1402 /*
1403 * Get the current/running component count.
1404 */
pj_ice_strans_get_running_comp_cnt(pj_ice_strans * ice_st)1405 PJ_DEF(unsigned) pj_ice_strans_get_running_comp_cnt(pj_ice_strans *ice_st)
1406 {
1407 PJ_ASSERT_RETURN(ice_st, PJ_EINVAL);
1408
1409 if (ice_st->ice && ice_st->ice->rcand_cnt) {
1410 return ice_st->ice->comp_cnt;
1411 } else {
1412 return ice_st->comp_cnt;
1413 }
1414 }
1415
1416
1417 /*
1418 * Get the ICE username fragment and password of the ICE session.
1419 */
pj_ice_strans_get_ufrag_pwd(pj_ice_strans * ice_st,pj_str_t * loc_ufrag,pj_str_t * loc_pwd,pj_str_t * rem_ufrag,pj_str_t * rem_pwd)1420 PJ_DEF(pj_status_t) pj_ice_strans_get_ufrag_pwd( pj_ice_strans *ice_st,
1421 pj_str_t *loc_ufrag,
1422 pj_str_t *loc_pwd,
1423 pj_str_t *rem_ufrag,
1424 pj_str_t *rem_pwd)
1425 {
1426 PJ_ASSERT_RETURN(ice_st && ice_st->ice, PJ_EINVALIDOP);
1427
1428 if (loc_ufrag) *loc_ufrag = ice_st->ice->rx_ufrag;
1429 if (loc_pwd) *loc_pwd = ice_st->ice->rx_pass;
1430
1431 if (rem_ufrag || rem_pwd) {
1432 // In trickle ICE, remote may send initial SDP with empty candidates
1433 //PJ_ASSERT_RETURN(ice_st->ice->rcand_cnt != 0, PJ_EINVALIDOP);
1434 if (rem_ufrag) *rem_ufrag = ice_st->ice->tx_ufrag;
1435 if (rem_pwd) *rem_pwd = ice_st->ice->tx_pass;
1436 }
1437
1438 return PJ_SUCCESS;
1439 }
1440
1441 /*
1442 * Get number of candidates
1443 */
pj_ice_strans_get_cands_count(pj_ice_strans * ice_st,unsigned comp_id)1444 PJ_DEF(unsigned) pj_ice_strans_get_cands_count(pj_ice_strans *ice_st,
1445 unsigned comp_id)
1446 {
1447 unsigned i, cnt;
1448
1449 PJ_ASSERT_RETURN(ice_st && ice_st->ice && comp_id &&
1450 comp_id <= ice_st->comp_cnt, 0);
1451
1452 cnt = 0;
1453 for (i=0; i<ice_st->ice->lcand_cnt; ++i) {
1454 if (ice_st->ice->lcand[i].comp_id != comp_id)
1455 continue;
1456 ++cnt;
1457 }
1458
1459 return cnt;
1460 }
1461
1462 /*
1463 * Enum candidates
1464 */
pj_ice_strans_enum_cands(pj_ice_strans * ice_st,unsigned comp_id,unsigned * count,pj_ice_sess_cand cand[])1465 PJ_DEF(pj_status_t) pj_ice_strans_enum_cands(pj_ice_strans *ice_st,
1466 unsigned comp_id,
1467 unsigned *count,
1468 pj_ice_sess_cand cand[])
1469 {
1470 unsigned i, cnt;
1471
1472 PJ_ASSERT_RETURN(ice_st && ice_st->ice && comp_id &&
1473 comp_id <= ice_st->comp_cnt && count && cand, PJ_EINVAL);
1474
1475 cnt = 0;
1476 for (i=0; i<ice_st->ice->lcand_cnt && cnt<*count; ++i) {
1477 if (ice_st->ice->lcand[i].comp_id != comp_id)
1478 continue;
1479 pj_memcpy(&cand[cnt], &ice_st->ice->lcand[i],
1480 sizeof(pj_ice_sess_cand));
1481 ++cnt;
1482 }
1483
1484 *count = cnt;
1485 return PJ_SUCCESS;
1486 }
1487
1488 /*
1489 * Get default candidate.
1490 */
pj_ice_strans_get_def_cand(pj_ice_strans * ice_st,unsigned comp_id,pj_ice_sess_cand * cand)1491 PJ_DEF(pj_status_t) pj_ice_strans_get_def_cand( pj_ice_strans *ice_st,
1492 unsigned comp_id,
1493 pj_ice_sess_cand *cand)
1494 {
1495 const pj_ice_sess_check *valid_pair;
1496
1497 PJ_ASSERT_RETURN(ice_st && comp_id && comp_id <= ice_st->comp_cnt &&
1498 cand, PJ_EINVAL);
1499
1500 valid_pair = pj_ice_strans_get_valid_pair(ice_st, comp_id);
1501 if (valid_pair) {
1502 pj_memcpy(cand, valid_pair->lcand, sizeof(pj_ice_sess_cand));
1503 } else {
1504 pj_ice_strans_comp *comp = ice_st->comp[comp_id - 1];
1505 pj_assert(comp->default_cand<comp->cand_cnt);
1506 pj_memcpy(cand, &comp->cand_list[comp->default_cand],
1507 sizeof(pj_ice_sess_cand));
1508 }
1509 return PJ_SUCCESS;
1510 }
1511
1512 /*
1513 * Get the current ICE role.
1514 */
pj_ice_strans_get_role(pj_ice_strans * ice_st)1515 PJ_DEF(pj_ice_sess_role) pj_ice_strans_get_role(pj_ice_strans *ice_st)
1516 {
1517 PJ_ASSERT_RETURN(ice_st && ice_st->ice, PJ_ICE_SESS_ROLE_UNKNOWN);
1518 return ice_st->ice->role;
1519 }
1520
1521 /*
1522 * Change session role.
1523 */
pj_ice_strans_change_role(pj_ice_strans * ice_st,pj_ice_sess_role new_role)1524 PJ_DEF(pj_status_t) pj_ice_strans_change_role( pj_ice_strans *ice_st,
1525 pj_ice_sess_role new_role)
1526 {
1527 PJ_ASSERT_RETURN(ice_st && ice_st->ice, PJ_EINVALIDOP);
1528 return pj_ice_sess_change_role(ice_st->ice, new_role);
1529 }
1530
setup_turn_perm(pj_ice_strans * ice_st)1531 static pj_status_t setup_turn_perm( pj_ice_strans *ice_st)
1532 {
1533 unsigned n;
1534 pj_status_t status;
1535
1536 for (n = 0; n < ice_st->cfg.turn_tp_cnt; ++n) {
1537 unsigned i, comp_cnt;
1538
1539 comp_cnt = pj_ice_strans_get_running_comp_cnt(ice_st);
1540 for (i=0; i<comp_cnt; ++i) {
1541 pj_ice_strans_comp *comp = ice_st->comp[i];
1542 pj_turn_session_info info;
1543 pj_sockaddr addrs[PJ_ICE_ST_MAX_CAND];
1544 unsigned j, count=0;
1545 unsigned rem_cand_cnt;
1546 const pj_ice_sess_cand *rem_cand;
1547
1548 if (!comp->turn[n].sock)
1549 continue;
1550
1551 status = pj_turn_sock_get_info(comp->turn[n].sock, &info);
1552 if (status != PJ_SUCCESS || info.state != PJ_TURN_STATE_READY)
1553 continue;
1554
1555 /* Gather remote addresses for this component */
1556 rem_cand_cnt = ice_st->ice->rcand_cnt;
1557 rem_cand = ice_st->ice->rcand;
1558 if (status != PJ_SUCCESS)
1559 continue;
1560
1561 for (j=0; j<rem_cand_cnt && count<PJ_ARRAY_SIZE(addrs); ++j) {
1562 if (rem_cand[j].comp_id==i+1 &&
1563 rem_cand[j].addr.addr.sa_family==
1564 ice_st->cfg.turn_tp[n].af)
1565 {
1566 pj_sockaddr_cp(&addrs[count++], &rem_cand[j].addr);
1567 }
1568 }
1569
1570 if (count && !comp->turn[n].err_cnt && comp->turn[n].sock) {
1571 status = pj_turn_sock_set_perm(
1572 comp->turn[n].sock, count,
1573 addrs, PJ_ICE_ST_USE_TURN_PERMANENT_PERM);
1574 if (status != PJ_SUCCESS) {
1575 pj_ice_strans_stop_ice(ice_st);
1576 return status;
1577 }
1578 }
1579 }
1580 }
1581
1582 return PJ_SUCCESS;
1583 }
1584
1585 /*
1586 * Start ICE processing !
1587 */
pj_ice_strans_start_ice(pj_ice_strans * ice_st,const pj_str_t * rem_ufrag,const pj_str_t * rem_passwd,unsigned rem_cand_cnt,const pj_ice_sess_cand rem_cand[])1588 PJ_DEF(pj_status_t) pj_ice_strans_start_ice( pj_ice_strans *ice_st,
1589 const pj_str_t *rem_ufrag,
1590 const pj_str_t *rem_passwd,
1591 unsigned rem_cand_cnt,
1592 const pj_ice_sess_cand rem_cand[])
1593 {
1594 pj_status_t status;
1595
1596 PJ_ASSERT_RETURN(ice_st, PJ_EINVAL);
1597 PJ_ASSERT_RETURN(ice_st->ice, PJ_EINVALIDOP);
1598
1599 /* Mark start time */
1600 pj_gettimeofday(&ice_st->start_time);
1601
1602 /* Update check list */
1603 status = pj_ice_strans_update_check_list(ice_st, rem_ufrag, rem_passwd,
1604 rem_cand_cnt, rem_cand,
1605 !ice_st->ice->is_trickling);
1606 if (status != PJ_SUCCESS)
1607 return status;
1608
1609 /* If we have TURN candidate, now is the time to create the permissions */
1610 status = setup_turn_perm(ice_st);
1611 if (status != PJ_SUCCESS) {
1612 pj_ice_strans_stop_ice(ice_st);
1613 return status;
1614 }
1615
1616 /* Start ICE negotiation! */
1617 status = pj_ice_sess_start_check(ice_st->ice);
1618 if (status != PJ_SUCCESS) {
1619 pj_ice_strans_stop_ice(ice_st);
1620 return status;
1621 }
1622
1623 ice_st->state = PJ_ICE_STRANS_STATE_NEGO;
1624 return status;
1625 }
1626
1627
1628 /*
1629 * Update check list after discovering and conveying new local ICE candidate,
1630 * or receiving update of remote ICE candidates in trickle ICE.
1631 */
pj_ice_strans_update_check_list(pj_ice_strans * ice_st,const pj_str_t * rem_ufrag,const pj_str_t * rem_passwd,unsigned rem_cand_cnt,const pj_ice_sess_cand rem_cand[],pj_bool_t rcand_end)1632 PJ_DEF(pj_status_t) pj_ice_strans_update_check_list(
1633 pj_ice_strans *ice_st,
1634 const pj_str_t *rem_ufrag,
1635 const pj_str_t *rem_passwd,
1636 unsigned rem_cand_cnt,
1637 const pj_ice_sess_cand rem_cand[],
1638 pj_bool_t rcand_end)
1639 {
1640 pj_bool_t checklist_created;
1641 pj_status_t status;
1642
1643 PJ_ASSERT_RETURN(ice_st && ((rem_cand_cnt==0) ||
1644 (rem_ufrag && rem_passwd && rem_cand)),
1645 PJ_EINVAL);
1646 PJ_ASSERT_RETURN(ice_st->ice, PJ_EINVALIDOP);
1647
1648 pj_grp_lock_acquire(ice_st->grp_lock);
1649
1650 checklist_created = ice_st->ice->tx_ufrag.slen > 0;
1651
1652 /* Create checklist (if not yet) */
1653 if (rem_ufrag && !checklist_created) {
1654 status = pj_ice_sess_create_check_list(ice_st->ice, rem_ufrag,
1655 rem_passwd, rem_cand_cnt,
1656 rem_cand);
1657 if (status != PJ_SUCCESS) {
1658 PJ_PERROR(4,(ice_st->obj_name, status,
1659 "Failed setting up remote ufrag"));
1660 pj_grp_lock_release(ice_st->grp_lock);
1661 return status;
1662 }
1663 }
1664
1665 /* Update checklist for trickling ICE */
1666 if (ice_st->ice->is_trickling) {
1667 if (rcand_end && !ice_st->rem_cand_end)
1668 ice_st->rem_cand_end = PJ_TRUE;
1669
1670 status = pj_ice_sess_update_check_list(
1671 ice_st->ice, rem_ufrag, rem_passwd,
1672 (checklist_created? rem_cand_cnt:0), rem_cand,
1673 (ice_st->rem_cand_end && ice_st->loc_cand_end));
1674 if (status != PJ_SUCCESS) {
1675 PJ_PERROR(4,(ice_st->obj_name, status,
1676 "Failed updating checklist"));
1677 pj_grp_lock_release(ice_st->grp_lock);
1678 return status;
1679 }
1680 }
1681
1682 /* Update TURN permissions if periodic check has been started. */
1683 if (pj_ice_strans_sess_is_running(ice_st)) {
1684 status = setup_turn_perm(ice_st);
1685 if (status != PJ_SUCCESS) {
1686 PJ_PERROR(4,(ice_st->obj_name, status,
1687 "Failed setting up TURN permission"));
1688 pj_grp_lock_release(ice_st->grp_lock);
1689 return status;
1690 }
1691 }
1692
1693 pj_grp_lock_release(ice_st->grp_lock);
1694
1695 return PJ_SUCCESS;
1696 }
1697
1698
1699 /*
1700 * Get valid pair.
1701 */
1702 PJ_DEF(const pj_ice_sess_check*)
pj_ice_strans_get_valid_pair(const pj_ice_strans * ice_st,unsigned comp_id)1703 pj_ice_strans_get_valid_pair(const pj_ice_strans *ice_st,
1704 unsigned comp_id)
1705 {
1706 PJ_ASSERT_RETURN(ice_st && comp_id && comp_id <= ice_st->comp_cnt,
1707 NULL);
1708
1709 if (ice_st->ice == NULL)
1710 return NULL;
1711
1712 return ice_st->ice->comp[comp_id-1].valid_check;
1713 }
1714
1715 /*
1716 * Stop ICE!
1717 */
pj_ice_strans_stop_ice(pj_ice_strans * ice_st)1718 PJ_DEF(pj_status_t) pj_ice_strans_stop_ice(pj_ice_strans *ice_st)
1719 {
1720 PJ_ASSERT_RETURN(ice_st, PJ_EINVAL);
1721
1722 /* Protect with group lock, since this may cause race condition with
1723 * pj_ice_strans_sendto2().
1724 * See ticket #1877.
1725 */
1726 pj_grp_lock_acquire(ice_st->grp_lock);
1727
1728 if (ice_st->ice) {
1729 pj_ice_sess_destroy(ice_st->ice);
1730 ice_st->ice = NULL;
1731 }
1732
1733 ice_st->state = PJ_ICE_STRANS_STATE_INIT;
1734
1735 pj_grp_lock_release(ice_st->grp_lock);
1736
1737 return PJ_SUCCESS;
1738 }
1739
use_buffer(pj_ice_strans * ice_st,unsigned comp_id,const void * data,pj_size_t data_len,const pj_sockaddr_t * dst_addr,int dst_addr_len,void ** buffer)1740 static pj_status_t use_buffer( pj_ice_strans *ice_st,
1741 unsigned comp_id,
1742 const void *data,
1743 pj_size_t data_len,
1744 const pj_sockaddr_t *dst_addr,
1745 int dst_addr_len,
1746 void **buffer )
1747 {
1748 unsigned idx;
1749 pj_status_t status;
1750
1751 /* Allocate send buffer, if necessary. */
1752 status = alloc_send_buf(ice_st, data_len);
1753 if (status != PJ_SUCCESS)
1754 return status;
1755
1756 if (ice_st->is_pending && ice_st->empty_idx == ice_st->buf_idx) {
1757 /* We don't use buffer or there's no more empty buffer. */
1758 return PJ_EBUSY;
1759 }
1760
1761 idx = ice_st->empty_idx;
1762 ice_st->empty_idx = (ice_st->empty_idx + 1) % ice_st->num_buf;
1763 ice_st->send_buf[idx].comp_id = comp_id;
1764 ice_st->send_buf[idx].data_len = data_len;
1765 pj_assert(ice_st->buf_size >= data_len);
1766 pj_memcpy(ice_st->send_buf[idx].buffer, data, data_len);
1767 pj_sockaddr_cp(&ice_st->send_buf[idx].dst_addr, dst_addr);
1768 ice_st->send_buf[idx].dst_addr_len = dst_addr_len;
1769 *buffer = ice_st->send_buf[idx].buffer;
1770
1771 if (ice_st->is_pending) {
1772 /* We'll continue later since there's still a pending send. */
1773 return PJ_EPENDING;
1774 }
1775
1776 ice_st->is_pending = PJ_TRUE;
1777 ice_st->buf_idx = idx;
1778
1779 return PJ_SUCCESS;
1780 }
1781
1782 /*
1783 * Application wants to send outgoing packet.
1784 */
send_data(pj_ice_strans * ice_st,unsigned comp_id,const void * data,pj_size_t data_len,const pj_sockaddr_t * dst_addr,int dst_addr_len,pj_bool_t use_buf,pj_bool_t call_cb)1785 static pj_status_t send_data(pj_ice_strans *ice_st,
1786 unsigned comp_id,
1787 const void *data,
1788 pj_size_t data_len,
1789 const pj_sockaddr_t *dst_addr,
1790 int dst_addr_len,
1791 pj_bool_t use_buf,
1792 pj_bool_t call_cb)
1793 {
1794 pj_ice_strans_comp *comp;
1795 pj_ice_sess_cand *def_cand;
1796 void *buf = (void *)data;
1797 pj_status_t status;
1798
1799 PJ_ASSERT_RETURN(ice_st && comp_id && comp_id <= ice_st->comp_cnt &&
1800 dst_addr && dst_addr_len, PJ_EINVAL);
1801
1802 comp = ice_st->comp[comp_id-1];
1803
1804 /* Check that default candidate for the component exists */
1805 if (comp->default_cand >= comp->cand_cnt) {
1806 status = PJ_EINVALIDOP;
1807 if (call_cb)
1808 on_data_sent(ice_st, -status);
1809 return status;
1810 }
1811
1812 /* Protect with group lock, since this may cause race condition with
1813 * pj_ice_strans_stop_ice().
1814 * See ticket #1877.
1815 */
1816 pj_grp_lock_acquire(ice_st->grp_lock);
1817
1818 if (use_buf && ice_st->num_buf > 0) {
1819 status = use_buffer(ice_st, comp_id, data, data_len, dst_addr,
1820 dst_addr_len, &buf);
1821
1822 if (status == PJ_EPENDING || status != PJ_SUCCESS) {
1823 pj_grp_lock_release(ice_st->grp_lock);
1824 return status;
1825 }
1826 }
1827
1828 /* If ICE is available, send data with ICE. If ICE nego is not completed
1829 * yet, ICE will try to send using any valid candidate pair. For any
1830 * failure, it will fallback to sending with the default candidate
1831 * selected during initialization.
1832 *
1833 * https://trac.pjsip.org/repos/ticket/1416:
1834 * Once ICE has failed, also send data with the default candidate.
1835 */
1836 if (ice_st->ice && ice_st->state <= PJ_ICE_STRANS_STATE_RUNNING) {
1837 status = pj_ice_sess_send_data(ice_st->ice, comp_id, buf, data_len);
1838 if (status == PJ_SUCCESS || status == PJ_EPENDING) {
1839 pj_grp_lock_release(ice_st->grp_lock);
1840 goto on_return;
1841 }
1842 }
1843
1844 pj_grp_lock_release(ice_st->grp_lock);
1845
1846 def_cand = &comp->cand_list[comp->default_cand];
1847
1848 if (def_cand->status == PJ_SUCCESS) {
1849 unsigned tp_idx = GET_TP_IDX(def_cand->transport_id);
1850
1851 if (def_cand->type == PJ_ICE_CAND_TYPE_RELAYED) {
1852
1853 enum {
1854 msg_disable_ind = 0xFFFF &
1855 ~(PJ_STUN_SESS_LOG_TX_IND|
1856 PJ_STUN_SESS_LOG_RX_IND)
1857 };
1858
1859 /* https://trac.pjsip.org/repos/ticket/1316 */
1860 if (comp->turn[tp_idx].sock == NULL) {
1861 /* TURN socket error */
1862 status = PJ_EINVALIDOP;
1863 goto on_return;
1864 }
1865
1866 if (!comp->turn[tp_idx].log_off) {
1867 /* Disable logging for Send/Data indications */
1868 PJ_LOG(5,(ice_st->obj_name,
1869 "Disabling STUN Indication logging for "
1870 "component %d", comp->comp_id));
1871 pj_turn_sock_set_log(comp->turn[tp_idx].sock,
1872 msg_disable_ind);
1873 comp->turn[tp_idx].log_off = PJ_TRUE;
1874 }
1875
1876 status = pj_turn_sock_sendto(comp->turn[tp_idx].sock,
1877 (const pj_uint8_t*)buf,
1878 (unsigned)data_len,
1879 dst_addr, dst_addr_len);
1880 goto on_return;
1881 } else {
1882 const pj_sockaddr_t *dest_addr;
1883 unsigned dest_addr_len;
1884
1885 if (comp->ipv4_mapped) {
1886 if (comp->synth_addr_len == 0 ||
1887 pj_sockaddr_cmp(&comp->dst_addr, dst_addr) != 0)
1888 {
1889 status = pj_sockaddr_synthesize(pj_AF_INET6(),
1890 &comp->synth_addr,
1891 dst_addr);
1892 if (status != PJ_SUCCESS)
1893 goto on_return;
1894
1895 pj_sockaddr_cp(&comp->dst_addr, dst_addr);
1896 comp->synth_addr_len = pj_sockaddr_get_len(
1897 &comp->synth_addr);
1898 }
1899 dest_addr = &comp->synth_addr;
1900 dest_addr_len = comp->synth_addr_len;
1901 } else {
1902 dest_addr = dst_addr;
1903 dest_addr_len = dst_addr_len;
1904 }
1905
1906 status = pj_stun_sock_sendto(comp->stun[tp_idx].sock, NULL, buf,
1907 (unsigned)data_len, 0, dest_addr,
1908 dest_addr_len);
1909 goto on_return;
1910 }
1911
1912 } else
1913 status = PJ_EINVALIDOP;
1914
1915 on_return:
1916 /* We continue later in on_data_sent() callback. */
1917 if (status == PJ_EPENDING)
1918 return status;
1919
1920 if (call_cb) {
1921 on_data_sent(ice_st, (status == PJ_SUCCESS? data_len: -status));
1922 } else {
1923 check_pending_send(ice_st);
1924 }
1925
1926 return status;
1927 }
1928
1929
1930 #if !DEPRECATED_FOR_TICKET_2229
1931 /*
1932 * Application wants to send outgoing packet.
1933 */
pj_ice_strans_sendto(pj_ice_strans * ice_st,unsigned comp_id,const void * data,pj_size_t data_len,const pj_sockaddr_t * dst_addr,int dst_addr_len)1934 PJ_DEF(pj_status_t) pj_ice_strans_sendto( pj_ice_strans *ice_st,
1935 unsigned comp_id,
1936 const void *data,
1937 pj_size_t data_len,
1938 const pj_sockaddr_t *dst_addr,
1939 int dst_addr_len)
1940 {
1941 pj_status_t status;
1942
1943 PJ_LOG(1, (ice_st->obj_name, "pj_ice_strans_sendto() is deprecated. "
1944 "Application is recommended to use "
1945 "pj_ice_strans_sendto2() instead."));
1946 status = send_data(ice_st, comp_id, data, data_len, dst_addr,
1947 dst_addr_len, PJ_TRUE, PJ_FALSE);
1948 if (status == PJ_EPENDING)
1949 status = PJ_SUCCESS;
1950
1951 return status;
1952 }
1953 #endif
1954
1955
1956 /*
1957 * Application wants to send outgoing packet.
1958 */
pj_ice_strans_sendto2(pj_ice_strans * ice_st,unsigned comp_id,const void * data,pj_size_t data_len,const pj_sockaddr_t * dst_addr,int dst_addr_len)1959 PJ_DEF(pj_status_t) pj_ice_strans_sendto2(pj_ice_strans *ice_st,
1960 unsigned comp_id,
1961 const void *data,
1962 pj_size_t data_len,
1963 const pj_sockaddr_t *dst_addr,
1964 int dst_addr_len)
1965 {
1966 ice_st->call_send_cb = PJ_TRUE;
1967 return send_data(ice_st, comp_id, data, data_len, dst_addr,
1968 dst_addr_len, PJ_TRUE, PJ_FALSE);
1969 }
1970
on_valid_pair(pj_ice_sess * ice)1971 static void on_valid_pair(pj_ice_sess *ice)
1972 {
1973 pj_time_val t;
1974 unsigned msec;
1975 pj_ice_strans *ice_st = (pj_ice_strans *)ice->user_data;
1976 pj_ice_strans_cb cb = ice_st->cb;
1977 pj_status_t status = PJ_SUCCESS;
1978
1979 pj_grp_lock_add_ref(ice_st->grp_lock);
1980
1981 pj_gettimeofday(&t);
1982 PJ_TIME_VAL_SUB(t, ice_st->start_time);
1983 msec = PJ_TIME_VAL_MSEC(t);
1984
1985 if (cb.on_valid_pair) {
1986 unsigned i;
1987 enum {
1988 msg_disable_ind = 0xFFFF & ~(PJ_STUN_SESS_LOG_TX_IND |
1989 PJ_STUN_SESS_LOG_RX_IND)
1990 };
1991
1992 PJ_LOG(4,
1993 (ice_st->obj_name, "First ICE candidate nominated in %ds:%03d",
1994 msec / 1000, msec % 1000));
1995
1996 for (i = 0; i < ice_st->comp_cnt; ++i) {
1997 const pj_ice_sess_check *check;
1998 pj_ice_strans_comp *comp = ice_st->comp[i];
1999
2000 check = pj_ice_strans_get_valid_pair(ice_st, i + 1);
2001 if (check) {
2002 char lip[PJ_INET6_ADDRSTRLEN + 10];
2003 char rip[PJ_INET6_ADDRSTRLEN + 10];
2004 unsigned tp_idx = GET_TP_IDX(check->lcand->transport_id);
2005 unsigned tp_typ = GET_TP_TYPE(check->lcand->transport_id);
2006
2007 pj_sockaddr_print(&check->lcand->addr, lip, sizeof(lip), 3);
2008 pj_sockaddr_print(&check->rcand->addr, rip, sizeof(rip), 3);
2009
2010 if (tp_typ == TP_TURN) {
2011 /* Activate channel binding for the remote address
2012 * for more efficient data transfer using TURN.
2013 */
2014 status = pj_turn_sock_bind_channel(
2015 comp->turn[tp_idx].sock, &check->rcand->addr,
2016 sizeof(check->rcand->addr));
2017
2018 /* Disable logging for Send/Data indications */
2019 PJ_LOG(5, (ice_st->obj_name,
2020 "Disabling STUN Indication logging for "
2021 "component %d",
2022 i + 1));
2023 pj_turn_sock_set_log(comp->turn[tp_idx].sock,
2024 msg_disable_ind);
2025 comp->turn[tp_idx].log_off = PJ_TRUE;
2026 }
2027
2028 PJ_LOG(4, (ice_st->obj_name,
2029 " Comp %d: "
2030 "sending from %s candidate %s to "
2031 "%s candidate %s",
2032 i + 1, pj_ice_get_cand_type_name(check->lcand->type),
2033 lip, pj_ice_get_cand_type_name(check->rcand->type),
2034 rip));
2035
2036 } else {
2037 PJ_LOG(4, (ice_st->obj_name, "Comp %d: disabled", i + 1));
2038 }
2039 }
2040
2041 ice_st->state = (status == PJ_SUCCESS) ? PJ_ICE_STRANS_STATE_RUNNING :
2042 PJ_ICE_STRANS_STATE_FAILED;
2043
2044 pj_log_push_indent();
2045 (*cb.on_valid_pair)(ice_st);
2046 pj_log_pop_indent();
2047 }
2048
2049 pj_grp_lock_dec_ref(ice_st->grp_lock);
2050 }
2051
2052 /*
2053 * Callback called by ICE session when ICE processing is complete, either
2054 * successfully or with failure.
2055 */
on_ice_complete(pj_ice_sess * ice,pj_status_t status)2056 static void on_ice_complete(pj_ice_sess *ice, pj_status_t status)
2057 {
2058 pj_ice_strans *ice_st = (pj_ice_strans*)ice->user_data;
2059 pj_time_val t;
2060 unsigned msec;
2061 pj_ice_strans_cb cb = ice_st->cb;
2062
2063 pj_grp_lock_add_ref(ice_st->grp_lock);
2064
2065 pj_gettimeofday(&t);
2066 PJ_TIME_VAL_SUB(t, ice_st->start_time);
2067 msec = PJ_TIME_VAL_MSEC(t);
2068
2069 if (cb.on_ice_complete) {
2070 if (status != PJ_SUCCESS) {
2071 PJ_PERROR(4,(ice_st->obj_name, status,
2072 "ICE negotiation failed after %ds:%03d",
2073 msec/1000, msec%1000));
2074 } else {
2075 unsigned i;
2076 enum {
2077 msg_disable_ind = 0xFFFF &
2078 ~(PJ_STUN_SESS_LOG_TX_IND|
2079 PJ_STUN_SESS_LOG_RX_IND)
2080 };
2081
2082 PJ_LOG(4,(ice_st->obj_name,
2083 "ICE negotiation success after %ds:%03d",
2084 msec/1000, msec%1000));
2085
2086 for (i=0; i<ice_st->comp_cnt; ++i) {
2087 const pj_ice_sess_check *check;
2088 pj_ice_strans_comp *comp = ice_st->comp[i];
2089
2090 check = pj_ice_strans_get_valid_pair(ice_st, i+1);
2091 if (check) {
2092 char lip[PJ_INET6_ADDRSTRLEN+10];
2093 char rip[PJ_INET6_ADDRSTRLEN+10];
2094 unsigned tp_idx = GET_TP_IDX(check->lcand->transport_id);
2095 unsigned tp_typ = GET_TP_TYPE(check->lcand->transport_id);
2096
2097 pj_sockaddr_print(&check->lcand->addr, lip,
2098 sizeof(lip), 3);
2099 pj_sockaddr_print(&check->rcand->addr, rip,
2100 sizeof(rip), 3);
2101
2102 if (tp_typ == TP_TURN) {
2103 /* Activate channel binding for the remote address
2104 * for more efficient data transfer using TURN.
2105 */
2106 status = pj_turn_sock_bind_channel(
2107 comp->turn[tp_idx].sock,
2108 &check->rcand->addr,
2109 sizeof(check->rcand->addr));
2110
2111 /* Disable logging for Send/Data indications */
2112 PJ_LOG(5,(ice_st->obj_name,
2113 "Disabling STUN Indication logging for "
2114 "component %d", i+1));
2115 pj_turn_sock_set_log(comp->turn[tp_idx].sock,
2116 msg_disable_ind);
2117 comp->turn[tp_idx].log_off = PJ_TRUE;
2118 }
2119
2120 PJ_LOG(4,(ice_st->obj_name, " Comp %d: "
2121 "sending from %s candidate %s to "
2122 "%s candidate %s",
2123 i+1,
2124 pj_ice_get_cand_type_name(check->lcand->type),
2125 lip,
2126 pj_ice_get_cand_type_name(check->rcand->type),
2127 rip));
2128
2129 } else {
2130 PJ_LOG(4,(ice_st->obj_name,
2131 "Comp %d: disabled", i+1));
2132 }
2133 }
2134 }
2135
2136 ice_st->state = (status==PJ_SUCCESS) ? PJ_ICE_STRANS_STATE_RUNNING :
2137 PJ_ICE_STRANS_STATE_FAILED;
2138
2139 pj_log_push_indent();
2140 (*cb.on_ice_complete)(ice_st, PJ_ICE_STRANS_OP_NEGOTIATION, status);
2141 pj_log_pop_indent();
2142
2143 }
2144
2145 pj_grp_lock_dec_ref(ice_st->grp_lock);
2146 }
2147
2148 /*
2149 * Callback called by ICE session when it wants to send outgoing packet.
2150 */
ice_tx_pkt(pj_ice_sess * ice,unsigned comp_id,unsigned transport_id,const void * pkt,pj_size_t size,const pj_sockaddr_t * dst_addr,unsigned dst_addr_len)2151 static pj_status_t ice_tx_pkt(pj_ice_sess *ice,
2152 unsigned comp_id,
2153 unsigned transport_id,
2154 const void *pkt, pj_size_t size,
2155 const pj_sockaddr_t *dst_addr,
2156 unsigned dst_addr_len)
2157 {
2158 pj_ice_strans *ice_st = (pj_ice_strans*)ice->user_data;
2159 pj_ice_strans_comp *comp;
2160 pj_status_t status;
2161 void *buf = (void *)pkt;
2162 pj_bool_t use_buf = PJ_FALSE;
2163 #if defined(ENABLE_TRACE) && (ENABLE_TRACE != 0)
2164 char daddr[PJ_INET6_ADDRSTRLEN];
2165 #endif
2166 unsigned tp_idx = GET_TP_IDX(transport_id);
2167 unsigned tp_typ = GET_TP_TYPE(transport_id);
2168
2169 PJ_ASSERT_RETURN(comp_id && comp_id <= ice_st->comp_cnt, PJ_EINVAL);
2170
2171 pj_grp_lock_acquire(ice_st->grp_lock);
2172 if (ice_st->num_buf > 0 &&
2173 (!ice_st->send_buf ||
2174 ice_st->send_buf[ice_st->buf_idx].buffer != pkt))
2175 {
2176 use_buf = PJ_TRUE;
2177 status = use_buffer(ice_st, comp_id, pkt, size, dst_addr,
2178 dst_addr_len, &buf);
2179 if (status == PJ_EPENDING || status != PJ_SUCCESS) {
2180 pj_grp_lock_release(ice_st->grp_lock);
2181 return status;
2182 }
2183 }
2184 pj_grp_lock_release(ice_st->grp_lock);
2185
2186 comp = ice_st->comp[comp_id-1];
2187
2188 TRACE_PKT((comp->ice_st->obj_name,
2189 "Component %d TX packet to %s:%d with transport %d",
2190 comp_id,
2191 pj_sockaddr_print(dst_addr, daddr, sizeof(addr), 2),
2192 pj_sockaddr_get_port(dst_addr),
2193 tp_typ));
2194
2195 if (tp_typ == TP_TURN) {
2196 if (comp->turn[tp_idx].sock) {
2197 status = pj_turn_sock_sendto(comp->turn[tp_idx].sock,
2198 (const pj_uint8_t*)buf,
2199 (unsigned)size,
2200 dst_addr, dst_addr_len);
2201 } else {
2202 status = PJ_EINVALIDOP;
2203 }
2204 } else if (tp_typ == TP_STUN) {
2205 const pj_sockaddr_t *dest_addr;
2206 unsigned dest_addr_len;
2207
2208 if (comp->ipv4_mapped) {
2209 if (comp->synth_addr_len == 0 ||
2210 pj_sockaddr_cmp(&comp->dst_addr, dst_addr) != 0)
2211 {
2212 status = pj_sockaddr_synthesize(pj_AF_INET6(),
2213 &comp->synth_addr, dst_addr);
2214 if (status != PJ_SUCCESS) {
2215 goto on_return;
2216 }
2217
2218 pj_sockaddr_cp(&comp->dst_addr, dst_addr);
2219 comp->synth_addr_len = pj_sockaddr_get_len(&comp->synth_addr);
2220 }
2221 dest_addr = &comp->synth_addr;
2222 dest_addr_len = comp->synth_addr_len;
2223 } else {
2224 dest_addr = dst_addr;
2225 dest_addr_len = dst_addr_len;
2226 }
2227
2228 status = pj_stun_sock_sendto(comp->stun[tp_idx].sock, NULL,
2229 buf, (unsigned)size, 0,
2230 dest_addr, dest_addr_len);
2231 } else {
2232 pj_assert(!"Invalid transport ID");
2233 status = PJ_EINVALIDOP;
2234 }
2235
2236 on_return:
2237 if (use_buf && status != PJ_EPENDING) {
2238 pj_grp_lock_acquire(ice_st->grp_lock);
2239 if (ice_st->num_buf > 0) {
2240 ice_st->buf_idx = (ice_st->buf_idx + 1) % ice_st->num_buf;
2241 pj_assert(ice_st->buf_idx == ice_st->empty_idx);
2242 }
2243 ice_st->is_pending = PJ_FALSE;
2244 pj_grp_lock_release(ice_st->grp_lock);
2245 }
2246
2247 return status;
2248 }
2249
2250 /*
2251 * Callback called by ICE session when it receives application data.
2252 */
ice_rx_data(pj_ice_sess * ice,unsigned comp_id,unsigned transport_id,void * pkt,pj_size_t size,const pj_sockaddr_t * src_addr,unsigned src_addr_len)2253 static void ice_rx_data(pj_ice_sess *ice,
2254 unsigned comp_id,
2255 unsigned transport_id,
2256 void *pkt, pj_size_t size,
2257 const pj_sockaddr_t *src_addr,
2258 unsigned src_addr_len)
2259 {
2260 pj_ice_strans *ice_st = (pj_ice_strans*)ice->user_data;
2261
2262 PJ_UNUSED_ARG(transport_id);
2263
2264 if (ice_st->cb.on_rx_data) {
2265 (*ice_st->cb.on_rx_data)(ice_st, comp_id, pkt, size,
2266 src_addr, src_addr_len);
2267 }
2268 }
2269
check_pending_send(pj_ice_strans * ice_st)2270 static void check_pending_send(pj_ice_strans *ice_st)
2271 {
2272 pj_grp_lock_acquire(ice_st->grp_lock);
2273
2274 if (ice_st->num_buf > 0)
2275 ice_st->buf_idx = (ice_st->buf_idx + 1) % ice_st->num_buf;
2276
2277 if (ice_st->num_buf > 0 && ice_st->buf_idx != ice_st->empty_idx) {
2278 /* There's some pending send. Send it one by one. */
2279 pending_send *ps = &ice_st->send_buf[ice_st->buf_idx];
2280
2281 pj_grp_lock_release(ice_st->grp_lock);
2282 send_data(ice_st, ps->comp_id, ps->buffer, ps->data_len,
2283 &ps->dst_addr, ps->dst_addr_len, PJ_FALSE, PJ_TRUE);
2284 } else {
2285 ice_st->is_pending = PJ_FALSE;
2286 pj_grp_lock_release(ice_st->grp_lock);
2287 }
2288 }
2289
2290 /* Notifification when asynchronous send operation via STUN/TURN
2291 * has completed.
2292 */
on_data_sent(pj_ice_strans * ice_st,pj_ssize_t sent)2293 static pj_bool_t on_data_sent(pj_ice_strans *ice_st, pj_ssize_t sent)
2294 {
2295 if (ice_st->destroy_req || !ice_st->is_pending)
2296 return PJ_TRUE;
2297
2298 if (ice_st->call_send_cb && ice_st->cb.on_data_sent) {
2299 (*ice_st->cb.on_data_sent)(ice_st, sent);
2300 }
2301
2302 check_pending_send(ice_st);
2303
2304 return PJ_TRUE;
2305 }
2306
2307 /* Notification when incoming packet has been received from
2308 * the STUN socket.
2309 */
stun_on_rx_data(pj_stun_sock * stun_sock,void * pkt,unsigned pkt_len,const pj_sockaddr_t * src_addr,unsigned addr_len)2310 static pj_bool_t stun_on_rx_data(pj_stun_sock *stun_sock,
2311 void *pkt,
2312 unsigned pkt_len,
2313 const pj_sockaddr_t *src_addr,
2314 unsigned addr_len)
2315 {
2316 sock_user_data *data;
2317 pj_ice_strans_comp *comp;
2318 pj_ice_strans *ice_st;
2319 pj_status_t status;
2320
2321 data = (sock_user_data*) pj_stun_sock_get_user_data(stun_sock);
2322 if (data == NULL) {
2323 /* We have disassociated ourselves from the STUN socket */
2324 return PJ_FALSE;
2325 }
2326
2327 comp = data->comp;
2328 ice_st = comp->ice_st;
2329
2330 pj_grp_lock_add_ref(ice_st->grp_lock);
2331
2332 if (ice_st->ice == NULL) {
2333 /* The ICE session is gone, but we're still receiving packets.
2334 * This could also happen if remote doesn't do ICE. So just
2335 * report this to application.
2336 */
2337 if (ice_st->cb.on_rx_data) {
2338 (*ice_st->cb.on_rx_data)(ice_st, comp->comp_id, pkt, pkt_len,
2339 src_addr, addr_len);
2340 }
2341
2342 } else {
2343
2344 /* Hand over the packet to ICE session */
2345 status = pj_ice_sess_on_rx_pkt(comp->ice_st->ice, comp->comp_id,
2346 data->transport_id,
2347 pkt, pkt_len,
2348 src_addr, addr_len);
2349
2350 if (status != PJ_SUCCESS) {
2351 ice_st_perror(comp->ice_st, "Error processing packet",
2352 status);
2353 }
2354 }
2355
2356 return pj_grp_lock_dec_ref(ice_st->grp_lock) ? PJ_FALSE : PJ_TRUE;
2357 }
2358
2359 /* Notifification when asynchronous send operation to the STUN socket
2360 * has completed.
2361 */
stun_on_data_sent(pj_stun_sock * stun_sock,pj_ioqueue_op_key_t * send_key,pj_ssize_t sent)2362 static pj_bool_t stun_on_data_sent(pj_stun_sock *stun_sock,
2363 pj_ioqueue_op_key_t *send_key,
2364 pj_ssize_t sent)
2365 {
2366 sock_user_data *data;
2367
2368 PJ_UNUSED_ARG(send_key);
2369
2370 data = (sock_user_data *)pj_stun_sock_get_user_data(stun_sock);
2371 if (!data || !data->comp || !data->comp->ice_st) return PJ_TRUE;
2372
2373 return on_data_sent(data->comp->ice_st, sent);
2374 }
2375
2376 /* Notification when the status of the STUN transport has changed. */
stun_on_status(pj_stun_sock * stun_sock,pj_stun_sock_op op,pj_status_t status)2377 static pj_bool_t stun_on_status(pj_stun_sock *stun_sock,
2378 pj_stun_sock_op op,
2379 pj_status_t status)
2380 {
2381 sock_user_data *data;
2382 pj_ice_strans_comp *comp;
2383 pj_ice_strans *ice_st;
2384 pj_ice_sess_cand *cand = NULL;
2385 unsigned i;
2386 int tp_idx;
2387
2388 pj_assert(status != PJ_EPENDING);
2389
2390 data = (sock_user_data*) pj_stun_sock_get_user_data(stun_sock);
2391 comp = data->comp;
2392 ice_st = comp->ice_st;
2393
2394 pj_grp_lock_add_ref(ice_st->grp_lock);
2395
2396 /* Wait until initialization completes */
2397 pj_grp_lock_acquire(ice_st->grp_lock);
2398
2399 /* Find the srflx cancidate */
2400 for (i=0; i<comp->cand_cnt; ++i) {
2401 if (comp->cand_list[i].type == PJ_ICE_CAND_TYPE_SRFLX &&
2402 comp->cand_list[i].transport_id == data->transport_id)
2403 {
2404 cand = &comp->cand_list[i];
2405 break;
2406 }
2407 }
2408
2409 pj_grp_lock_release(ice_st->grp_lock);
2410
2411 /* It is possible that we don't have srflx candidate even though this
2412 * callback is called. This could happen when we cancel adding srflx
2413 * candidate due to initialization error.
2414 */
2415 if (cand == NULL) {
2416 return pj_grp_lock_dec_ref(ice_st->grp_lock) ? PJ_FALSE : PJ_TRUE;
2417 }
2418
2419 tp_idx = GET_TP_IDX(data->transport_id);
2420
2421 switch (op) {
2422 case PJ_STUN_SOCK_DNS_OP:
2423 if (status != PJ_SUCCESS) {
2424 /* May not have cand, e.g. when error during init */
2425 if (cand)
2426 cand->status = status;
2427 if (!ice_st->cfg.stun_tp[tp_idx].ignore_stun_error) {
2428 sess_fail(ice_st, PJ_ICE_STRANS_OP_INIT,
2429 "DNS resolution failed", status);
2430 } else {
2431 PJ_LOG(4,(ice_st->obj_name,
2432 "STUN error is ignored for comp %d",
2433 comp->comp_id));
2434 }
2435 }
2436 break;
2437 case PJ_STUN_SOCK_BINDING_OP:
2438 case PJ_STUN_SOCK_MAPPED_ADDR_CHANGE:
2439 if (status == PJ_SUCCESS) {
2440 pj_stun_sock_info info;
2441
2442 status = pj_stun_sock_get_info(stun_sock, &info);
2443 if (status == PJ_SUCCESS) {
2444 char ipaddr[PJ_INET6_ADDRSTRLEN+10];
2445 const char *op_name = (op==PJ_STUN_SOCK_BINDING_OP) ?
2446 "Binding discovery complete" :
2447 "srflx address changed";
2448 pj_bool_t dup = PJ_FALSE;
2449 pj_bool_t init_done;
2450
2451 if (info.mapped_addr.addr.sa_family == pj_AF_INET() &&
2452 cand->base_addr.addr.sa_family == pj_AF_INET6())
2453 {
2454 /* We get an IPv4 mapped address for our IPv6
2455 * host address.
2456 */
2457 comp->ipv4_mapped = PJ_TRUE;
2458
2459 /* Find other host candidates with the same (IPv6)
2460 * address, and replace it with the new (IPv4)
2461 * mapped address.
2462 */
2463 for (i = 0; i < comp->cand_cnt; ++i) {
2464 pj_sockaddr *a1, *a2;
2465
2466 if (comp->cand_list[i].type != PJ_ICE_CAND_TYPE_HOST)
2467 continue;
2468
2469 a1 = &comp->cand_list[i].addr;
2470 a2 = &cand->base_addr;
2471 if (pj_memcmp(pj_sockaddr_get_addr(a1),
2472 pj_sockaddr_get_addr(a2),
2473 pj_sockaddr_get_addr_len(a1)) == 0)
2474 {
2475 pj_uint16_t port = pj_sockaddr_get_port(a1);
2476 pj_sockaddr_cp(a1, &info.mapped_addr);
2477 if (port != pj_sockaddr_get_port(a2))
2478 pj_sockaddr_set_port(a1, port);
2479 pj_sockaddr_cp(&comp->cand_list[i].base_addr, a1);
2480 }
2481 }
2482 pj_sockaddr_cp(&cand->base_addr, &info.mapped_addr);
2483 pj_sockaddr_cp(&cand->rel_addr, &info.mapped_addr);
2484 }
2485
2486 /* Eliminate the srflx candidate if the address is
2487 * equal to other (host) candidates.
2488 */
2489 for (i=0; i<comp->cand_cnt; ++i) {
2490 if (comp->cand_list[i].type == PJ_ICE_CAND_TYPE_HOST &&
2491 pj_sockaddr_cmp(&comp->cand_list[i].addr,
2492 &info.mapped_addr) == 0)
2493 {
2494 dup = PJ_TRUE;
2495 break;
2496 }
2497 }
2498
2499 if (dup) {
2500 /* Duplicate found, remove the srflx candidate */
2501 unsigned idx = (unsigned)(cand - comp->cand_list);
2502
2503 /* Update default candidate index */
2504 if (comp->default_cand > idx) {
2505 --comp->default_cand;
2506 } else if (comp->default_cand == idx) {
2507 comp->default_cand = 0;
2508 }
2509
2510 /* Remove srflx candidate */
2511 pj_array_erase(comp->cand_list, sizeof(comp->cand_list[0]),
2512 comp->cand_cnt, idx);
2513 --comp->cand_cnt;
2514 } else {
2515 /* Otherwise update the address */
2516 pj_sockaddr_cp(&cand->addr, &info.mapped_addr);
2517 cand->status = PJ_SUCCESS;
2518
2519 /* Add the candidate (for trickle ICE) */
2520 if (pj_ice_strans_has_sess(ice_st)) {
2521 status = pj_ice_sess_add_cand(
2522 ice_st->ice,
2523 comp->comp_id,
2524 cand->transport_id,
2525 cand->type,
2526 cand->local_pref,
2527 &cand->foundation,
2528 &cand->addr,
2529 &cand->base_addr,
2530 &cand->rel_addr,
2531 pj_sockaddr_get_len(&cand->addr),
2532 NULL);
2533 }
2534 }
2535
2536 PJ_LOG(4,(comp->ice_st->obj_name,
2537 "Comp %d: %s, "
2538 "srflx address is %s",
2539 comp->comp_id, op_name,
2540 pj_sockaddr_print(&info.mapped_addr, ipaddr,
2541 sizeof(ipaddr), 3)));
2542
2543 sess_init_update(ice_st);
2544
2545 /* Invoke on_new_candidate() callback */
2546 init_done = (ice_st->state==PJ_ICE_STRANS_STATE_READY);
2547 if (op == PJ_STUN_SOCK_BINDING_OP && status == PJ_SUCCESS &&
2548 ice_st->cb.on_new_candidate && (!dup || init_done))
2549 {
2550 (*ice_st->cb.on_new_candidate)
2551 (ice_st, (dup? NULL:cand), init_done);
2552 }
2553
2554 if (op == PJ_STUN_SOCK_MAPPED_ADDR_CHANGE &&
2555 ice_st->cb.on_ice_complete)
2556 {
2557 (*ice_st->cb.on_ice_complete)(ice_st,
2558 PJ_ICE_STRANS_OP_ADDR_CHANGE,
2559 status);
2560 }
2561 }
2562 }
2563
2564 if (status != PJ_SUCCESS) {
2565 /* May not have cand, e.g. when error during init */
2566 if (cand)
2567 cand->status = status;
2568 if (!ice_st->cfg.stun_tp[tp_idx].ignore_stun_error ||
2569 comp->cand_cnt==1)
2570 {
2571 sess_fail(ice_st, PJ_ICE_STRANS_OP_INIT,
2572 "STUN binding request failed", status);
2573 } else {
2574 pj_bool_t init_done;
2575
2576 PJ_LOG(4,(ice_st->obj_name,
2577 "STUN error is ignored for comp %d",
2578 comp->comp_id));
2579
2580 if (cand) {
2581 unsigned idx = (unsigned)(cand - comp->cand_list);
2582
2583 /* Update default candidate index */
2584 if (comp->default_cand == idx) {
2585 comp->default_cand = !idx;
2586 }
2587 }
2588
2589 sess_init_update(ice_st);
2590
2591 /* Invoke on_new_candidate() callback */
2592 init_done = (ice_st->state==PJ_ICE_STRANS_STATE_READY);
2593 if (op == PJ_STUN_SOCK_BINDING_OP &&
2594 ice_st->cb.on_new_candidate && init_done)
2595 {
2596 (*ice_st->cb.on_new_candidate) (ice_st, NULL, PJ_TRUE);
2597 }
2598 }
2599 }
2600 break;
2601 case PJ_STUN_SOCK_KEEP_ALIVE_OP:
2602 if (status != PJ_SUCCESS) {
2603 pj_assert(cand != NULL);
2604 cand->status = status;
2605 if (!ice_st->cfg.stun_tp[tp_idx].ignore_stun_error) {
2606 sess_fail(ice_st, PJ_ICE_STRANS_OP_INIT,
2607 "STUN keep-alive failed", status);
2608 } else {
2609 PJ_LOG(4,(ice_st->obj_name, "STUN error is ignored"));
2610 }
2611 }
2612 break;
2613 }
2614
2615 return pj_grp_lock_dec_ref(ice_st->grp_lock)? PJ_FALSE : PJ_TRUE;
2616 }
2617
2618 /* Callback when TURN socket has received a packet */
turn_on_rx_data(pj_turn_sock * turn_sock,void * pkt,unsigned pkt_len,const pj_sockaddr_t * peer_addr,unsigned addr_len)2619 static void turn_on_rx_data(pj_turn_sock *turn_sock,
2620 void *pkt,
2621 unsigned pkt_len,
2622 const pj_sockaddr_t *peer_addr,
2623 unsigned addr_len)
2624 {
2625 pj_ice_strans_comp *comp;
2626 sock_user_data *data;
2627 pj_status_t status;
2628
2629 data = (sock_user_data*) pj_turn_sock_get_user_data(turn_sock);
2630 if (data == NULL) {
2631 /* We have disassociated ourselves from the TURN socket */
2632 return;
2633 }
2634
2635 comp = data->comp;
2636
2637 pj_grp_lock_add_ref(comp->ice_st->grp_lock);
2638
2639 if (comp->ice_st->ice == NULL) {
2640 /* The ICE session is gone, but we're still receiving packets.
2641 * This could also happen if remote doesn't do ICE and application
2642 * specifies TURN as the default address in SDP.
2643 * So in this case just give the packet to application.
2644 */
2645 if (comp->ice_st->cb.on_rx_data) {
2646 (*comp->ice_st->cb.on_rx_data)(comp->ice_st, comp->comp_id, pkt,
2647 pkt_len, peer_addr, addr_len);
2648 }
2649
2650 } else {
2651
2652 /* Hand over the packet to ICE */
2653 status = pj_ice_sess_on_rx_pkt(comp->ice_st->ice, comp->comp_id,
2654 data->transport_id, pkt, pkt_len,
2655 peer_addr, addr_len);
2656
2657 if (status != PJ_SUCCESS) {
2658 ice_st_perror(comp->ice_st,
2659 "Error processing packet from TURN relay",
2660 status);
2661 }
2662 }
2663
2664 pj_grp_lock_dec_ref(comp->ice_st->grp_lock);
2665 }
2666
2667 /* Notifification when asynchronous send operation to the TURN socket
2668 * has completed.
2669 */
turn_on_data_sent(pj_turn_sock * turn_sock,pj_ssize_t sent)2670 static pj_bool_t turn_on_data_sent(pj_turn_sock *turn_sock,
2671 pj_ssize_t sent)
2672 {
2673 sock_user_data *data;
2674
2675 data = (sock_user_data *)pj_turn_sock_get_user_data(turn_sock);
2676 if (!data || !data->comp || !data->comp->ice_st) return PJ_TRUE;
2677
2678 return on_data_sent(data->comp->ice_st, sent);
2679 }
2680
2681 /* Callback when TURN client state has changed */
turn_on_state(pj_turn_sock * turn_sock,pj_turn_state_t old_state,pj_turn_state_t new_state)2682 static void turn_on_state(pj_turn_sock *turn_sock, pj_turn_state_t old_state,
2683 pj_turn_state_t new_state)
2684 {
2685 pj_ice_strans_comp *comp;
2686 sock_user_data *data;
2687 int tp_idx;
2688
2689 data = (sock_user_data*) pj_turn_sock_get_user_data(turn_sock);
2690 if (data == NULL) {
2691 /* Not interested in further state notification once the relay is
2692 * disconnecting.
2693 */
2694 return;
2695 }
2696
2697 comp = data->comp;
2698 tp_idx = GET_TP_IDX(data->transport_id);
2699
2700 PJ_LOG(5,(comp->ice_st->obj_name, "TURN client state changed %s --> %s",
2701 pj_turn_state_name(old_state), pj_turn_state_name(new_state)));
2702 pj_log_push_indent();
2703
2704 pj_grp_lock_add_ref(comp->ice_st->grp_lock);
2705
2706 if (new_state == PJ_TURN_STATE_READY) {
2707 pj_turn_session_info rel_info;
2708 char ipaddr[PJ_INET6_ADDRSTRLEN+8];
2709 pj_ice_sess_cand *cand = NULL;
2710 unsigned i, cand_idx = 0xFF;
2711
2712 comp->turn[tp_idx].err_cnt = 0;
2713
2714 /* Get allocation info */
2715 pj_turn_sock_get_info(turn_sock, &rel_info);
2716
2717 /* Wait until initialization completes */
2718 pj_grp_lock_acquire(comp->ice_st->grp_lock);
2719
2720 /* Find relayed candidate in the component */
2721 for (i=0; i<comp->cand_cnt; ++i) {
2722 if (comp->cand_list[i].type == PJ_ICE_CAND_TYPE_RELAYED &&
2723 comp->cand_list[i].transport_id == data->transport_id)
2724 {
2725 cand = &comp->cand_list[i];
2726 cand_idx = i;
2727 break;
2728 }
2729 }
2730
2731 pj_grp_lock_release(comp->ice_st->grp_lock);
2732
2733 if (cand == NULL)
2734 goto on_return;
2735
2736 /* Update candidate */
2737 pj_sockaddr_cp(&cand->addr, &rel_info.relay_addr);
2738 pj_sockaddr_cp(&cand->base_addr, &rel_info.relay_addr);
2739 pj_sockaddr_cp(&cand->rel_addr, &rel_info.mapped_addr);
2740 pj_ice_calc_foundation(comp->ice_st->pool, &cand->foundation,
2741 PJ_ICE_CAND_TYPE_RELAYED,
2742 &rel_info.relay_addr);
2743 cand->status = PJ_SUCCESS;
2744
2745 /* Set default candidate to relay */
2746 if (comp->cand_list[comp->default_cand].type!=PJ_ICE_CAND_TYPE_RELAYED
2747 || (comp->ice_st->cfg.af != pj_AF_UNSPEC() &&
2748 comp->cand_list[comp->default_cand].addr.addr.sa_family
2749 != comp->ice_st->cfg.af))
2750 {
2751 comp->default_cand = (unsigned)(cand - comp->cand_list);
2752 }
2753
2754 /* Prefer IPv4 relay as default candidate for better connectivity
2755 * with IPv4 endpoints.
2756 */
2757 /*
2758 if (cand->addr.addr.sa_family != pj_AF_INET()) {
2759 for (i=0; i<comp->cand_cnt; ++i) {
2760 if (comp->cand_list[i].type == PJ_ICE_CAND_TYPE_RELAYED &&
2761 comp->cand_list[i].addr.addr.sa_family == pj_AF_INET() &&
2762 comp->cand_list[i].status == PJ_SUCCESS)
2763 {
2764 comp->default_cand = i;
2765 break;
2766 }
2767 }
2768 }
2769 */
2770
2771 PJ_LOG(4,(comp->ice_st->obj_name,
2772 "Comp %d/%d: TURN allocation (tpid=%d) complete, "
2773 "relay address is %s",
2774 comp->comp_id, cand_idx, cand->transport_id,
2775 pj_sockaddr_print(&rel_info.relay_addr, ipaddr,
2776 sizeof(ipaddr), 3)));
2777
2778 /* For trickle ICE, add the candidate to ICE session and setup TURN
2779 * permission for remote candidates.
2780 */
2781 if (comp->ice_st->cfg.opt.trickle != PJ_ICE_SESS_TRICKLE_DISABLED &&
2782 pj_ice_strans_has_sess(comp->ice_st))
2783 {
2784 pj_sockaddr addrs[PJ_ICE_ST_MAX_CAND];
2785 pj_ice_sess *sess = comp->ice_st->ice;
2786 unsigned j, count=0;
2787 pj_status_t status;
2788
2789 /* Add the candidate */
2790 status = pj_ice_sess_add_cand(comp->ice_st->ice,
2791 comp->comp_id,
2792 cand->transport_id,
2793 cand->type,
2794 cand->local_pref,
2795 &cand->foundation,
2796 &cand->addr,
2797 &cand->base_addr,
2798 &cand->rel_addr,
2799 pj_sockaddr_get_len(&cand->addr),
2800 NULL);
2801 if (status != PJ_SUCCESS) {
2802 PJ_PERROR(4,(comp->ice_st->obj_name, status,
2803 "Comp %d/%d: failed to add TURN (tpid=%d) to ICE",
2804 comp->comp_id, cand_idx, cand->transport_id));
2805 sess_fail(comp->ice_st, PJ_ICE_STRANS_OP_INIT,
2806 "adding TURN candidate failed", status);
2807 }
2808
2809 /* Gather remote addresses for this component */
2810 for (j=0; j<sess->rcand_cnt && count<PJ_ARRAY_SIZE(addrs); ++j) {
2811 if (sess->rcand[j].addr.addr.sa_family==
2812 rel_info.relay_addr.addr.sa_family)
2813 {
2814 pj_sockaddr_cp(&addrs[count++], &sess->rcand[j].addr);
2815 }
2816 }
2817
2818 if (count) {
2819 status = pj_turn_sock_set_perm(turn_sock, count, addrs, 0);
2820 if (status != PJ_SUCCESS) {
2821 PJ_PERROR(4,(comp->ice_st->obj_name, status,
2822 "Comp %d/%d: TURN set perm (tpid=%d) failed",
2823 comp->comp_id, cand_idx, cand->transport_id));
2824 sess_fail(comp->ice_st, PJ_ICE_STRANS_OP_INIT,
2825 "TURN set permission failed", status);
2826 }
2827 }
2828 }
2829
2830 sess_init_update(comp->ice_st);
2831
2832 /* Invoke on_new_candidate() callback */
2833 if (comp->ice_st->cb.on_new_candidate) {
2834 (*comp->ice_st->cb.on_new_candidate)
2835 (comp->ice_st, cand,
2836 (comp->ice_st->state==PJ_ICE_STRANS_STATE_READY));
2837 }
2838
2839 } else if ((old_state == PJ_TURN_STATE_RESOLVING ||
2840 old_state == PJ_TURN_STATE_RESOLVED ||
2841 old_state == PJ_TURN_STATE_ALLOCATING) &&
2842 new_state >= PJ_TURN_STATE_DEALLOCATING)
2843 {
2844 pj_ice_sess_cand *cand = NULL;
2845 unsigned i, cand_idx = 0xFF;
2846
2847 /* DNS resolution or TURN transport creation/allocation
2848 * has failed.
2849 */
2850 ++comp->turn[tp_idx].err_cnt;
2851
2852 /* Unregister ourself from the TURN relay */
2853 pj_turn_sock_set_user_data(turn_sock, NULL);
2854 comp->turn[tp_idx].sock = NULL;
2855
2856 /* Wait until initialization completes */
2857 pj_grp_lock_acquire(comp->ice_st->grp_lock);
2858
2859 /* Find relayed candidate in the component */
2860 for (i=0; i<comp->cand_cnt; ++i) {
2861 if (comp->cand_list[i].type == PJ_ICE_CAND_TYPE_RELAYED &&
2862 comp->cand_list[i].transport_id == data->transport_id)
2863 {
2864 cand = &comp->cand_list[i];
2865 cand_idx = i;
2866 break;
2867 }
2868 }
2869
2870 pj_grp_lock_release(comp->ice_st->grp_lock);
2871
2872 /* If the error happens during pj_turn_sock_create() or
2873 * pj_turn_sock_alloc(), the candidate hasn't been added
2874 * to the list.
2875 */
2876 if (cand) {
2877 pj_turn_session_info info;
2878
2879 pj_turn_sock_get_info(turn_sock, &info);
2880 cand->status = (old_state == PJ_TURN_STATE_RESOLVING)?
2881 PJ_ERESOLVE : info.last_status;
2882 PJ_LOG(4,(comp->ice_st->obj_name,
2883 "Comp %d/%d: TURN error (tpid=%d) during state %s",
2884 comp->comp_id, cand_idx, cand->transport_id,
2885 pj_turn_state_name(old_state)));
2886 }
2887
2888 sess_init_update(comp->ice_st);
2889
2890 /* Invoke on_new_candidate() callback */
2891 if (comp->ice_st->cb.on_new_candidate &&
2892 comp->ice_st->state==PJ_ICE_STRANS_STATE_READY)
2893 {
2894 (*comp->ice_st->cb.on_new_candidate)(comp->ice_st, NULL, PJ_TRUE);
2895 }
2896
2897 } else if (new_state >= PJ_TURN_STATE_DEALLOCATING) {
2898 pj_turn_session_info info;
2899
2900 ++comp->turn[tp_idx].err_cnt;
2901
2902 pj_turn_sock_get_info(turn_sock, &info);
2903
2904 /* Unregister ourself from the TURN relay */
2905 pj_turn_sock_set_user_data(turn_sock, NULL);
2906 comp->turn[tp_idx].sock = NULL;
2907
2908 /* Set session to fail on error. last_status PJ_SUCCESS means normal
2909 * deallocation, which should not trigger sess_fail as it may have
2910 * been initiated by ICE destroy
2911 */
2912 if (info.last_status != PJ_SUCCESS) {
2913 if (comp->ice_st->state < PJ_ICE_STRANS_STATE_READY) {
2914 sess_fail(comp->ice_st, PJ_ICE_STRANS_OP_INIT,
2915 "TURN allocation failed", info.last_status);
2916 } else if (comp->turn[tp_idx].err_cnt > 1) {
2917 sess_fail(comp->ice_st, PJ_ICE_STRANS_OP_KEEP_ALIVE,
2918 "TURN refresh failed", info.last_status);
2919 } else {
2920 PJ_PERROR(4,(comp->ice_st->obj_name, info.last_status,
2921 "Comp %d: TURN allocation failed, retrying",
2922 comp->comp_id));
2923 add_update_turn(comp->ice_st, comp, tp_idx,
2924 PJ_ICE_ST_MAX_CAND - comp->cand_cnt);
2925 }
2926 }
2927 }
2928
2929 on_return:
2930 pj_grp_lock_dec_ref(comp->ice_st->grp_lock);
2931
2932 pj_log_pop_indent();
2933 }
2934
2935