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 <pjsua-lib/pjsua.h>
21 #include <pjsua-lib/pjsua_internal.h>
22
23
24 #define THIS_FILE "pjsua_media.c"
25
26 #ifndef PJSUA_REQUIRE_CONSECUTIVE_RTCP_PORT
27 # define PJSUA_REQUIRE_CONSECUTIVE_RTCP_PORT 0
28 #endif
29
30 static void stop_media_stream(pjsua_call *call, unsigned med_idx);
31
pjsua_media_config_dup(pj_pool_t * pool,pjsua_media_config * dst,const pjsua_media_config * src)32 static void pjsua_media_config_dup(pj_pool_t *pool,
33 pjsua_media_config *dst,
34 const pjsua_media_config *src)
35 {
36 pj_memcpy(dst, src, sizeof(*src));
37 pj_strdup(pool, &dst->turn_server, &src->turn_server);
38 pj_stun_auth_cred_dup(pool, &dst->turn_auth_cred, &src->turn_auth_cred);
39 #if PJ_HAS_SSL_SOCK
40 pj_turn_sock_tls_cfg_dup(pool, &dst->turn_tls_setting,
41 &src->turn_tls_setting);
42 #endif
43 }
44
45
46 /**
47 * Init media subsystems.
48 */
pjsua_media_subsys_init(const pjsua_media_config * cfg)49 pj_status_t pjsua_media_subsys_init(const pjsua_media_config *cfg)
50 {
51 pj_status_t status;
52
53 pj_log_push_indent();
54
55 /* Specify which audio device settings are save-able */
56 pjsua_var.aud_svmask = 0xFFFFFFFF;
57 /* These are not-settable */
58 pjsua_var.aud_svmask &= ~(PJMEDIA_AUD_DEV_CAP_EXT_FORMAT |
59 PJMEDIA_AUD_DEV_CAP_INPUT_SIGNAL_METER |
60 PJMEDIA_AUD_DEV_CAP_OUTPUT_SIGNAL_METER);
61 /* EC settings use different API */
62 pjsua_var.aud_svmask &= ~(PJMEDIA_AUD_DEV_CAP_EC |
63 PJMEDIA_AUD_DEV_CAP_EC_TAIL);
64
65 /* Copy configuration */
66 pjsua_media_config_dup(pjsua_var.pool, &pjsua_var.media_cfg, cfg);
67
68 /* Normalize configuration */
69 if (pjsua_var.media_cfg.snd_clock_rate == 0) {
70 pjsua_var.media_cfg.snd_clock_rate = pjsua_var.media_cfg.clock_rate;
71 }
72
73 if (pjsua_var.media_cfg.has_ioqueue &&
74 pjsua_var.media_cfg.thread_cnt == 0)
75 {
76 pjsua_var.media_cfg.thread_cnt = 1;
77 }
78
79 if (pjsua_var.media_cfg.max_media_ports < pjsua_var.ua_cfg.max_calls) {
80 pjsua_var.media_cfg.max_media_ports = pjsua_var.ua_cfg.max_calls + 2;
81 }
82
83 /* Create media endpoint. */
84 status = pjmedia_endpt_create(&pjsua_var.cp.factory,
85 pjsua_var.media_cfg.has_ioqueue? NULL :
86 pjsip_endpt_get_ioqueue(pjsua_var.endpt),
87 pjsua_var.media_cfg.thread_cnt,
88 &pjsua_var.med_endpt);
89 if (status != PJ_SUCCESS) {
90 pjsua_perror(THIS_FILE,
91 "Media stack initialization has returned error",
92 status);
93 goto on_error;
94 }
95
96 status = pjsua_aud_subsys_init();
97 if (status != PJ_SUCCESS)
98 goto on_error;
99
100 #if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
101 /* Initialize SRTP library (ticket #788). */
102 status = pjmedia_srtp_init_lib(pjsua_var.med_endpt);
103 if (status != PJ_SUCCESS) {
104 pjsua_perror(THIS_FILE, "Error initializing SRTP library",
105 status);
106 goto on_error;
107 }
108 #endif
109
110 /* Video */
111 #if PJMEDIA_HAS_VIDEO
112 status = pjsua_vid_subsys_init();
113 if (status != PJ_SUCCESS)
114 goto on_error;
115 #endif
116
117 /* Create event manager */
118 if (!pjmedia_event_mgr_instance()) {
119 status = pjmedia_event_mgr_create(pjsua_var.pool, 0, NULL);
120 if (status != PJ_SUCCESS) {
121 pjsua_perror(THIS_FILE, "Error creating PJMEDIA event manager",
122 status);
123 goto on_error;
124 }
125 }
126
127 pj_log_pop_indent();
128 return PJ_SUCCESS;
129
130 on_error:
131 pj_log_pop_indent();
132 return status;
133 }
134
135 /*
136 * Start pjsua media subsystem.
137 */
pjsua_media_subsys_start(void)138 pj_status_t pjsua_media_subsys_start(void)
139 {
140 pj_status_t status;
141
142 pj_log_push_indent();
143
144 #if DISABLED_FOR_TICKET_1185
145 /* Create media for calls, if none is specified */
146 if (pjsua_var.calls[0].media[0].tp == NULL) {
147 pjsua_transport_config transport_cfg;
148
149 /* Create default transport config */
150 pjsua_transport_config_default(&transport_cfg);
151 transport_cfg.port = DEFAULT_RTP_PORT;
152
153 status = pjsua_media_transports_create(&transport_cfg);
154 if (status != PJ_SUCCESS) {
155 pj_log_pop_indent();
156 return status;
157 }
158 }
159 #endif
160
161 /* Audio */
162 status = pjsua_aud_subsys_start();
163 if (status != PJ_SUCCESS) {
164 pj_log_pop_indent();
165 return status;
166 }
167
168 /* Video */
169 #if PJMEDIA_HAS_VIDEO
170 status = pjsua_vid_subsys_start();
171 if (status != PJ_SUCCESS) {
172 pjsua_aud_subsys_destroy();
173 pj_log_pop_indent();
174 return status;
175 }
176 #endif
177
178 /* Perform NAT detection */
179 // Performed only when STUN server resolution by pjsua_init() completed
180 // successfully (see ticket #1865).
181 //if (pjsua_var.ua_cfg.stun_srv_cnt) {
182 //status = pjsua_detect_nat_type();
183 //if (status != PJ_SUCCESS) {
184 // PJ_PERROR(1,(THIS_FILE, status, "NAT type detection failed"));
185 //}
186 //}
187
188 pj_log_pop_indent();
189 return PJ_SUCCESS;
190 }
191
192
193 /*
194 * Destroy pjsua media subsystem.
195 */
pjsua_media_subsys_destroy(unsigned flags)196 pj_status_t pjsua_media_subsys_destroy(unsigned flags)
197 {
198 PJ_UNUSED_ARG(flags);
199
200 PJ_LOG(4,(THIS_FILE, "Shutting down media.."));
201 pj_log_push_indent();
202
203 if (pjsua_var.med_endpt) {
204 /* Wait for media endpoint's worker threads to quit. */
205 pjmedia_endpt_stop_threads(pjsua_var.med_endpt);
206
207 pjsua_aud_subsys_destroy();
208 }
209
210 #if 0
211 // This part has been moved out to pjsua_destroy() (see also #1717).
212 /* Close media transports */
213 for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) {
214 /* TODO: check if we're not allowed to send to network in the
215 * "flags", and if so do not do TURN allocation...
216 */
217 PJ_UNUSED_ARG(flags);
218 pjsua_media_channel_deinit(i);
219 }
220 #endif
221
222 /* Destroy media endpoint. */
223 if (pjsua_var.med_endpt) {
224
225 # if PJMEDIA_HAS_VIDEO
226 pjsua_vid_subsys_destroy();
227 # endif
228
229 pjmedia_endpt_destroy(pjsua_var.med_endpt);
230 pjsua_var.med_endpt = NULL;
231
232 /* Deinitialize sound subsystem */
233 // Not necessary, as pjmedia_snd_deinit() should have been called
234 // in pjmedia_endpt_destroy().
235 //pjmedia_snd_deinit();
236 }
237
238 if (pjmedia_event_mgr_instance())
239 pjmedia_event_mgr_destroy(NULL);
240
241 pj_log_pop_indent();
242
243 return PJ_SUCCESS;
244 }
245
246 /*
247 * Create RTP and RTCP socket pair, and possibly resolve their public
248 * address via STUN.
249 */
create_rtp_rtcp_sock(pjsua_call_media * call_med,const pjsua_transport_config * cfg,pjmedia_sock_info * skinfo)250 static pj_status_t create_rtp_rtcp_sock(pjsua_call_media *call_med,
251 const pjsua_transport_config *cfg,
252 pjmedia_sock_info *skinfo)
253 {
254 enum {
255 RTP_RETRY = 100
256 };
257 int i;
258 pj_bool_t use_ipv6, use_nat64;
259 int af;
260 pj_sockaddr bound_addr;
261 pj_sockaddr mapped_addr[2];
262 pj_status_t status = PJ_SUCCESS;
263 char addr_buf[PJ_INET6_ADDRSTRLEN+10];
264 pjsua_acc *acc = &pjsua_var.acc[call_med->call->acc_id];
265 pj_sock_t sock[2];
266
267 use_ipv6 = (acc->cfg.ipv6_media_use != PJSUA_IPV6_DISABLED);
268 use_nat64 = (acc->cfg.nat64_opt != PJSUA_NAT64_DISABLED);
269 af = (use_ipv6 || use_nat64) ? pj_AF_INET6() : pj_AF_INET();
270
271 /* Make sure STUN server resolution has completed */
272 if ((!use_ipv6 || use_nat64) &&
273 pjsua_media_acc_is_using_stun(call_med->call->acc_id))
274 {
275 pj_bool_t retry_stun = (acc->cfg.media_stun_use &
276 PJSUA_STUN_RETRY_ON_FAILURE) ==
277 PJSUA_STUN_RETRY_ON_FAILURE;
278 status = resolve_stun_server(PJ_TRUE, retry_stun,
279 (unsigned)acc->cfg.nat64_opt);
280 if (status != PJ_SUCCESS) {
281 pjsua_perror(THIS_FILE, "Error resolving STUN server", status);
282 return status;
283 }
284 }
285
286 if (acc->next_rtp_port == 0 || cfg->port == 0)
287 acc->next_rtp_port = (pj_uint16_t)cfg->port;
288
289 for (i=0; i<2; ++i)
290 sock[i] = PJ_INVALID_SOCKET;
291
292 pj_sockaddr_init(af, &bound_addr, NULL, 0);
293 if (cfg->bound_addr.slen) {
294 status = pj_sockaddr_set_str_addr(af, &bound_addr, &cfg->bound_addr);
295 if (status != PJ_SUCCESS) {
296 pjsua_perror(THIS_FILE, "Unable to resolve transport bind address",
297 status);
298 return status;
299 }
300 }
301
302 /* Loop retry to bind RTP and RTCP sockets. */
303 for (i=0; i<RTP_RETRY; ++i, acc->next_rtp_port += 2) {
304
305 if (cfg->port > 0 && cfg->port_range > 0 &&
306 (acc->next_rtp_port > cfg->port + cfg->port_range ||
307 acc->next_rtp_port < cfg->port))
308 {
309 acc->next_rtp_port = (pj_uint16_t)cfg->port;
310 }
311
312 /* Create RTP socket. */
313 status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &sock[0]);
314 if (status != PJ_SUCCESS) {
315 pjsua_perror(THIS_FILE, "socket() error", status);
316 return status;
317 }
318
319 /* Apply QoS to RTP socket, if specified */
320 status = pj_sock_apply_qos2(sock[0], cfg->qos_type,
321 &cfg->qos_params,
322 2, THIS_FILE, "RTP socket");
323
324 /* Apply sockopt, if specified */
325 if (cfg->sockopt_params.cnt)
326 status = pj_sock_setsockopt_params(sock[0], &cfg->sockopt_params);
327
328 /* Bind RTP socket */
329 pj_sockaddr_set_port(&bound_addr, acc->next_rtp_port);
330 status=pj_sock_bind(sock[0], &bound_addr,
331 pj_sockaddr_get_len(&bound_addr));
332 if (status != PJ_SUCCESS) {
333 pj_sock_close(sock[0]);
334 sock[0] = PJ_INVALID_SOCKET;
335 continue;
336 }
337
338 /* If bound to random port, find out the port number. */
339 if (acc->next_rtp_port == 0) {
340 pj_sockaddr sock_addr;
341 int addr_len = sizeof(pj_sockaddr);
342
343 status = pj_sock_getsockname(sock[0], &sock_addr, &addr_len);
344 if (status != PJ_SUCCESS) {
345 pjsua_perror(THIS_FILE, "getsockname() error", status);
346 pj_sock_close(sock[0]);
347 return status;
348 }
349 acc->next_rtp_port = pj_sockaddr_get_port(&sock_addr);
350 }
351
352 /* Create RTCP socket. */
353 status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &sock[1]);
354 if (status != PJ_SUCCESS) {
355 pjsua_perror(THIS_FILE, "socket() error", status);
356 pj_sock_close(sock[0]);
357 return status;
358 }
359
360 /* Apply QoS to RTCP socket, if specified */
361 status = pj_sock_apply_qos2(sock[1], cfg->qos_type,
362 &cfg->qos_params,
363 2, THIS_FILE, "RTCP socket");
364
365 /* Apply sockopt, if specified */
366 if (cfg->sockopt_params.cnt)
367 status = pj_sock_setsockopt_params(sock[1], &cfg->sockopt_params);
368
369 /* Bind RTCP socket */
370 pj_sockaddr_set_port(&bound_addr, (pj_uint16_t)(acc->next_rtp_port+1));
371 status=pj_sock_bind(sock[1], &bound_addr,
372 pj_sockaddr_get_len(&bound_addr));
373 if (status != PJ_SUCCESS) {
374 pj_sock_close(sock[0]);
375 sock[0] = PJ_INVALID_SOCKET;
376
377 pj_sock_close(sock[1]);
378 sock[1] = PJ_INVALID_SOCKET;
379 continue;
380 }
381
382 /*
383 * If we're configured to use STUN, then find out the mapped address,
384 * and make sure that the mapped RTCP port is adjacent with the RTP.
385 */
386 if ((!use_ipv6 || use_nat64) &&
387 pjsua_media_acc_is_using_stun(call_med->call->acc_id) &&
388 pjsua_var.stun_srv.addr.sa_family != 0)
389 {
390 char ip_addr[PJ_INET6_ADDRSTRLEN];
391 pj_str_t stun_srv;
392 pj_sockaddr_in resolved_addr[2];
393 pjstun_setting stun_opt;
394
395 pj_sockaddr_print(&pjsua_var.stun_srv, ip_addr,sizeof(ip_addr),0);
396 stun_srv = pj_str(ip_addr);
397
398 pj_bzero(&stun_opt, sizeof(stun_opt));
399 stun_opt.use_stun2 = pjsua_var.ua_cfg.stun_map_use_stun2;
400 stun_opt.af = pjsua_var.stun_srv.addr.sa_family;
401 stun_opt.srv1 = stun_opt.srv2 = stun_srv;
402 stun_opt.port1 = stun_opt.port2 =
403 pj_sockaddr_get_port(&pjsua_var.stun_srv);
404 status=pjstun_get_mapped_addr2(&pjsua_var.cp.factory, &stun_opt,
405 2, sock, resolved_addr);
406 #if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \
407 PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0
408 /* Handle EPIPE (Broken Pipe) error, which happens on UDP socket
409 * after app wakes up from suspended state. In this case, simply
410 * just retry.
411 * P.S.: The magic status is PJ_STATUS_FROM_OS(EPIPE)
412 */
413 if (status == 120032) {
414 PJ_LOG(4,(THIS_FILE, "Got EPIPE error, retrying.."));
415 pj_sock_close(sock[0]);
416 sock[0] = PJ_INVALID_SOCKET;
417
418 pj_sock_close(sock[1]);
419 sock[1] = PJ_INVALID_SOCKET;
420
421 continue;
422 }
423 else
424 #endif
425
426 if (status != PJ_SUCCESS && pjsua_var.ua_cfg.stun_srv_cnt > 1 &&
427 ((acc->cfg.media_stun_use & PJSUA_STUN_RETRY_ON_FAILURE)==
428 PJSUA_STUN_RETRY_ON_FAILURE))
429 {
430 pj_str_t srv =
431 pjsua_var.ua_cfg.stun_srv[pjsua_var.stun_srv_idx];
432
433 PJ_LOG(4,(THIS_FILE, "Failed to get STUN mapped address, "
434 "retrying other STUN servers"));
435
436 if (pjsua_var.stun_srv_idx < pjsua_var.ua_cfg.stun_srv_cnt-1) {
437 PJSUA_LOCK();
438 /* Move the unusable STUN server to the last position
439 * as the least prioritize.
440 */
441 pj_array_erase(pjsua_var.ua_cfg.stun_srv,
442 sizeof(pj_str_t),
443 pjsua_var.ua_cfg.stun_srv_cnt,
444 pjsua_var.stun_srv_idx);
445
446 pj_array_insert(pjsua_var.ua_cfg.stun_srv,
447 sizeof(pj_str_t),
448 pjsua_var.ua_cfg.stun_srv_cnt-1,
449 pjsua_var.ua_cfg.stun_srv_cnt-1,
450 &srv);
451
452 PJSUA_UNLOCK();
453 }
454 status=pjsua_update_stun_servers(pjsua_var.ua_cfg.stun_srv_cnt,
455 pjsua_var.ua_cfg.stun_srv,
456 PJ_TRUE);
457 if (status == PJ_SUCCESS) {
458 if (pjsua_var.stun_srv.addr.sa_family != 0) {
459 pj_sockaddr_print(&pjsua_var.stun_srv,
460 ip_addr, sizeof(ip_addr), 0);
461 stun_srv = pj_str(ip_addr);
462 } else {
463 stun_srv.slen = 0;
464 }
465
466 stun_opt.af = pjsua_var.stun_srv.addr.sa_family;
467 stun_opt.srv1 = stun_opt.srv2 = stun_srv;
468 stun_opt.port1 = stun_opt.port2 =
469 pj_sockaddr_get_port(&pjsua_var.stun_srv);
470 status = pjstun_get_mapped_addr2(&pjsua_var.cp.factory,
471 &stun_opt, 2, sock,
472 resolved_addr);
473 }
474 }
475
476 if (status != PJ_SUCCESS) {
477 if (!pjsua_var.ua_cfg.stun_ignore_failure) {
478 pjsua_perror(THIS_FILE, "STUN resolve error", status);
479 goto on_error;
480 }
481
482 PJ_LOG(4,(THIS_FILE, "Ignoring STUN resolve error %d",
483 status));
484
485 if (!pj_sockaddr_has_addr(&bound_addr)) {
486 pj_sockaddr addr;
487
488 /* Get local IP address. */
489 status = pj_gethostip(af, &addr);
490 if (status != PJ_SUCCESS)
491 goto on_error;
492
493 pj_sockaddr_copy_addr(&bound_addr, &addr);
494 }
495
496 for (i=0; i<2; ++i) {
497 pj_sockaddr_init(af, &mapped_addr[i], NULL, 0);
498 pj_sockaddr_copy_addr(&mapped_addr[i], &bound_addr);
499 pj_sockaddr_set_port(&mapped_addr[i],
500 (pj_uint16_t)(acc->next_rtp_port+i));
501 }
502 break;
503 }
504
505 pj_sockaddr_cp(&mapped_addr[0], &resolved_addr[0]);
506 pj_sockaddr_cp(&mapped_addr[1], &resolved_addr[1]);
507
508 #if PJSUA_REQUIRE_CONSECUTIVE_RTCP_PORT
509 if (pj_sockaddr_get_port(&mapped_addr[1]) ==
510 pj_sockaddr_get_port(&mapped_addr[0])+1)
511 {
512 /* Success! */
513 break;
514 }
515
516 pj_sock_close(sock[0]);
517 sock[0] = PJ_INVALID_SOCKET;
518
519 pj_sock_close(sock[1]);
520 sock[1] = PJ_INVALID_SOCKET;
521 #else
522 if (pj_sockaddr_get_port(&mapped_addr[1]) !=
523 pj_sockaddr_get_port(&mapped_addr[0])+1)
524 {
525 PJ_LOG(4,(THIS_FILE,
526 "Note: STUN mapped RTCP port %d is not adjacent"
527 " to RTP port %d",
528 pj_sockaddr_get_port(&mapped_addr[1]),
529 pj_sockaddr_get_port(&mapped_addr[0])));
530 }
531 /* Success! */
532 break;
533 #endif
534
535 } else if (cfg->public_addr.slen) {
536
537 status = pj_sockaddr_init(af, &mapped_addr[0], &cfg->public_addr,
538 (pj_uint16_t)acc->next_rtp_port);
539 if (status != PJ_SUCCESS)
540 goto on_error;
541
542 status = pj_sockaddr_init(af, &mapped_addr[1], &cfg->public_addr,
543 (pj_uint16_t)(acc->next_rtp_port+1));
544 if (status != PJ_SUCCESS)
545 goto on_error;
546
547 break;
548
549 } else {
550 if (acc->cfg.allow_sdp_nat_rewrite && acc->reg_mapped_addr.slen) {
551 pj_status_t status2;
552
553 /* Take the address from mapped addr as seen by registrar */
554 status2 = pj_sockaddr_set_str_addr(af, &bound_addr,
555 &acc->reg_mapped_addr);
556 if (status2 != PJ_SUCCESS) {
557 /* just leave bound_addr with whatever it was
558 pj_bzero(pj_sockaddr_get_addr(&bound_addr),
559 pj_sockaddr_get_addr_len(&bound_addr));
560 */
561 }
562 }
563
564 if (!pj_sockaddr_has_addr(&bound_addr)) {
565 pj_sockaddr addr;
566
567 /* Get local IP address. */
568 status = pj_gethostip(af, &addr);
569 if (status != PJ_SUCCESS)
570 goto on_error;
571
572 pj_sockaddr_copy_addr(&bound_addr, &addr);
573 }
574
575 for (i=0; i<2; ++i) {
576 pj_sockaddr_init(af, &mapped_addr[i], NULL, 0);
577 pj_sockaddr_copy_addr(&mapped_addr[i], &bound_addr);
578 pj_sockaddr_set_port(&mapped_addr[i],
579 (pj_uint16_t)(acc->next_rtp_port+i));
580 }
581
582 break;
583 }
584 }
585
586 if (sock[0] == PJ_INVALID_SOCKET) {
587 PJ_LOG(1,(THIS_FILE,
588 "Unable to find appropriate RTP/RTCP ports combination"));
589 goto on_error;
590 }
591
592
593 skinfo->rtp_sock = sock[0];
594 pj_sockaddr_cp(&skinfo->rtp_addr_name, &mapped_addr[0]);
595
596 skinfo->rtcp_sock = sock[1];
597 pj_sockaddr_cp(&skinfo->rtcp_addr_name, &mapped_addr[1]);
598
599 PJ_LOG(4,(THIS_FILE, "RTP%s socket reachable at %s",
600 (call_med->enable_rtcp_mux? " & RTCP": ""),
601 pj_sockaddr_print(&skinfo->rtp_addr_name, addr_buf,
602 sizeof(addr_buf), 3)));
603 PJ_LOG(4,(THIS_FILE, "RTCP socket reachable at %s",
604 pj_sockaddr_print(&skinfo->rtcp_addr_name, addr_buf,
605 sizeof(addr_buf), 3)));
606
607 acc->next_rtp_port += 2;
608 return PJ_SUCCESS;
609
610 on_error:
611 for (i=0; i<2; ++i) {
612 if (sock[i] != PJ_INVALID_SOCKET)
613 pj_sock_close(sock[i]);
614 }
615 return status;
616 }
617
618 /* Create normal UDP media transports */
create_udp_media_transport(const pjsua_transport_config * cfg,pjsua_call_media * call_med)619 static pj_status_t create_udp_media_transport(const pjsua_transport_config *cfg,
620 pjsua_call_media *call_med)
621 {
622 pjmedia_sock_info skinfo;
623 pj_status_t status;
624
625 status = create_rtp_rtcp_sock(call_med, cfg, &skinfo);
626 if (status != PJ_SUCCESS) {
627 pjsua_perror(THIS_FILE, "Unable to create RTP/RTCP socket",
628 status);
629 goto on_error;
630 }
631
632 status = pjmedia_transport_udp_attach(pjsua_var.med_endpt, NULL,
633 &skinfo, 0, &call_med->tp);
634 if (status != PJ_SUCCESS) {
635 pjsua_perror(THIS_FILE, "Unable to create media transport",
636 status);
637 goto on_error;
638 }
639
640 pjmedia_transport_simulate_lost(call_med->tp, PJMEDIA_DIR_ENCODING,
641 pjsua_var.media_cfg.tx_drop_pct);
642
643 pjmedia_transport_simulate_lost(call_med->tp, PJMEDIA_DIR_DECODING,
644 pjsua_var.media_cfg.rx_drop_pct);
645
646 call_med->tp_ready = PJ_SUCCESS;
647
648 return PJ_SUCCESS;
649
650 on_error:
651 if (call_med->tp)
652 pjmedia_transport_close(call_med->tp);
653
654 return status;
655 }
656
657 /* Create loop media transport */
create_loop_media_transport(const pjsua_transport_config * cfg,pjsua_call_media * call_med)658 static pj_status_t create_loop_media_transport(
659 const pjsua_transport_config *cfg,
660 pjsua_call_media *call_med)
661 {
662 pj_status_t status;
663 pjmedia_loop_tp_setting opt;
664 pj_bool_t use_ipv6, use_nat64;
665 int af;
666 pjsua_acc *acc = &pjsua_var.acc[call_med->call->acc_id];
667
668 use_ipv6 = (acc->cfg.ipv6_media_use != PJSUA_IPV6_DISABLED);
669 use_nat64 = (acc->cfg.nat64_opt != PJSUA_NAT64_DISABLED);
670 af = (use_ipv6 || use_nat64) ? pj_AF_INET6() : pj_AF_INET();
671
672 pjmedia_loop_tp_setting_default(&opt);
673 opt.af = af;
674 if (cfg->bound_addr.slen)
675 opt.addr = cfg->bound_addr;
676
677 if (acc->next_rtp_port == 0 || cfg->port == 0)
678 acc->next_rtp_port = (pj_uint16_t)cfg->port;
679
680 if (cfg->port > 0 && cfg->port_range > 0 &&
681 (acc->next_rtp_port > cfg->port + cfg->port_range ||
682 acc->next_rtp_port < cfg->port))
683 {
684 acc->next_rtp_port = (pj_uint16_t)cfg->port;
685 }
686 opt.port = acc->next_rtp_port;
687 acc->next_rtp_port += 2;
688
689 opt.disable_rx=!pjsua_var.acc[call_med->call->acc_id].cfg.enable_loopback;
690 status = pjmedia_transport_loop_create2(pjsua_var.med_endpt, &opt,
691 &call_med->tp);
692 if (status != PJ_SUCCESS) {
693 pjsua_perror(THIS_FILE, "Unable to create loop media transport",
694 status);
695 goto on_error;
696 }
697
698 pjmedia_transport_simulate_lost(call_med->tp, PJMEDIA_DIR_ENCODING,
699 pjsua_var.media_cfg.tx_drop_pct);
700
701 pjmedia_transport_simulate_lost(call_med->tp, PJMEDIA_DIR_DECODING,
702 pjsua_var.media_cfg.rx_drop_pct);
703
704 call_med->tp_ready = PJ_SUCCESS;
705
706 return PJ_SUCCESS;
707
708 on_error:
709 if (call_med->tp)
710 pjmedia_transport_close(call_med->tp);
711
712 return status;
713 }
714
715 #if DISABLED_FOR_TICKET_1185
716 /* Create normal UDP media transports */
create_udp_media_transports(pjsua_transport_config * cfg)717 static pj_status_t create_udp_media_transports(pjsua_transport_config *cfg)
718 {
719 unsigned i;
720 pj_status_t status;
721
722 for (i=0; i < pjsua_var.ua_cfg.max_calls; ++i) {
723 pjsua_call *call = &pjsua_var.calls[i];
724 unsigned strm_idx;
725
726 for (strm_idx=0; strm_idx < call->med_cnt; ++strm_idx) {
727 pjsua_call_media *call_med = &call->media[strm_idx];
728
729 status = create_udp_media_transport(cfg, &call_med->tp);
730 if (status != PJ_SUCCESS)
731 goto on_error;
732 }
733 }
734
735 return PJ_SUCCESS;
736
737 on_error:
738 for (i=0; i < pjsua_var.ua_cfg.max_calls; ++i) {
739 pjsua_call *call = &pjsua_var.calls[i];
740 unsigned strm_idx;
741
742 for (strm_idx=0; strm_idx < call->med_cnt; ++strm_idx) {
743 pjsua_call_media *call_med = &call->media[strm_idx];
744
745 if (call_med->tp) {
746 pjmedia_transport_close(call_med->tp);
747 call_med->tp = NULL;
748 }
749 }
750 }
751 return status;
752 }
753 #endif
754
755 /* Deferred callback to notify ICE init complete */
ice_init_complete_cb(void * user_data)756 static void ice_init_complete_cb(void *user_data)
757 {
758 pjsua_call_media *call_med = (pjsua_call_media*)user_data;
759
760 if (call_med->call == NULL || call_med->tp_ready == PJ_SUCCESS)
761 return;
762
763 /* No need to acquire_call() if we only change the tp_ready flag
764 * (i.e. transport is being created synchronously). Otherwise
765 * calling acquire_call() here may cause deadlock. See
766 * https://trac.pjsip.org/repos/ticket/1578
767 */
768 call_med->tp_ready = call_med->tp_result;
769
770 if (call_med->med_create_cb) {
771 pjsua_call *call = NULL;
772 pjsip_dialog *dlg = NULL;
773 pj_status_t status;
774
775 status = acquire_call("ice_init_complete_cb", call_med->call->index,
776 &call, &dlg);
777 if (status != PJ_SUCCESS) {
778 if (status != PJSIP_ESESSIONTERMINATED) {
779 /* Retry, if call is still active */
780 pjsua_schedule_timer2(&ice_init_complete_cb, call_med, 10);
781 }
782 return;
783 }
784
785 (*call_med->med_create_cb)(call_med, call_med->tp_ready,
786 call_med->call->secure_level, NULL);
787
788 if (dlg)
789 pjsip_dlg_dec_lock(dlg);
790 }
791 }
792
793 /* Deferred callback to notify ICE negotiation failure */
ice_failed_nego_cb(void * user_data)794 static void ice_failed_nego_cb(void *user_data)
795 {
796 int call_id = (int)(pj_ssize_t)user_data;
797 pjsua_call *call = NULL;
798 pjsip_dialog *dlg = NULL;
799 pj_status_t status;
800
801 status = acquire_call("ice_failed_nego_cb", call_id, &call, &dlg);
802 if (status != PJ_SUCCESS) {
803 if (status != PJSIP_ESESSIONTERMINATED) {
804 /* Retry, if call is still active */
805 pjsua_schedule_timer2(&ice_failed_nego_cb,
806 (void*)(pj_ssize_t)call_id, 10);
807 }
808 return;
809 }
810
811 if (!call->hanging_up)
812 pjsua_var.ua_cfg.cb.on_call_media_state(call_id);
813
814 if (dlg)
815 pjsip_dlg_dec_lock(dlg);
816
817 }
818
819 /* This callback is called when ICE negotiation completes */
on_ice_complete(pjmedia_transport * tp,pj_ice_strans_op op,pj_status_t result)820 static void on_ice_complete(pjmedia_transport *tp,
821 pj_ice_strans_op op,
822 pj_status_t result)
823 {
824 pjsua_call_media *call_med = (pjsua_call_media*)tp->user_data;
825 pjsua_call *call;
826
827 if (!call_med)
828 return;
829
830 call = call_med->call;
831
832 switch (op) {
833 case PJ_ICE_STRANS_OP_INIT:
834 call_med->tp_result = result;
835 pjsua_schedule_timer2(&ice_init_complete_cb, call_med, 1);
836 break;
837 case PJ_ICE_STRANS_OP_NEGOTIATION:
838 if (result == PJ_SUCCESS) {
839 /* Update RTP address */
840 pjmedia_transport_info tpinfo;
841 pjmedia_transport_info_init(&tpinfo);
842 pjmedia_transport_get_info(call_med->tp, &tpinfo);
843 pj_sockaddr_cp(&call_med->rtp_addr, &tpinfo.sock_info.rtp_addr_name);
844 } else {
845 call_med->state = PJSUA_CALL_MEDIA_ERROR;
846 call_med->dir = PJMEDIA_DIR_NONE;
847 if (call && !call->hanging_up &&
848 pjsua_var.ua_cfg.cb.on_call_media_state)
849 {
850 /* Defer the callback to a timer */
851 pjsua_schedule_timer2(&ice_failed_nego_cb,
852 (void*)(pj_ssize_t)call->index, 1);
853 }
854 }
855
856 /* Stop trickling */
857 if (call->trickle_ice.trickling < PJSUA_OP_STATE_DONE) {
858 call->trickle_ice.trickling = PJSUA_OP_STATE_DONE;
859 pjsua_cancel_timer(&call->trickle_ice.timer);
860 PJ_LOG(4,(THIS_FILE, "Call %d: ICE trickle stopped trickling as "
861 "ICE nego completed",
862 call->index));
863 }
864
865 /* Check if default ICE transport address is changed */
866 call->reinv_ice_sent = PJ_FALSE;
867 pjsua_call_schedule_reinvite_check(call, 0);
868 break;
869 case PJ_ICE_STRANS_OP_KEEP_ALIVE:
870 case PJ_ICE_STRANS_OP_ADDR_CHANGE:
871 if (result != PJ_SUCCESS) {
872 PJ_PERROR(4,(THIS_FILE, result,
873 "ICE keep alive failure for transport %d:%d",
874 call->index, call_med->idx));
875 }
876 if (!call->hanging_up &&
877 pjsua_var.ua_cfg.cb.on_call_media_transport_state)
878 {
879 pjsua_med_tp_state_info info;
880
881 pj_bzero(&info, sizeof(info));
882 info.med_idx = call_med->idx;
883 info.state = call_med->tp_st;
884 info.status = result;
885 info.ext_info = &op;
886 (*pjsua_var.ua_cfg.cb.on_call_media_transport_state)(
887 call->index, &info);
888 }
889 if (pjsua_var.ua_cfg.cb.on_ice_transport_error &&
890 op == PJ_ICE_STRANS_OP_KEEP_ALIVE)
891 {
892 pjsua_call_id id = call->index;
893 (*pjsua_var.ua_cfg.cb.on_ice_transport_error)(id, op, result,
894 NULL);
895 }
896 break;
897 }
898 }
899
900
901 /* Parse "HOST:PORT" format */
parse_host_port(const pj_str_t * host_port,pj_str_t * host,pj_uint16_t * port)902 static pj_status_t parse_host_port(const pj_str_t *host_port,
903 pj_str_t *host, pj_uint16_t *port)
904 {
905 pj_str_t str_port;
906
907 str_port.ptr = pj_strchr(host_port, ':');
908 if (str_port.ptr != NULL) {
909 int iport;
910
911 host->ptr = host_port->ptr;
912 host->slen = (str_port.ptr - host->ptr);
913 str_port.ptr++;
914 str_port.slen = host_port->slen - host->slen - 1;
915 iport = (int)pj_strtoul(&str_port);
916 if (iport < 1 || iport > 65535)
917 return PJ_EINVAL;
918 *port = (pj_uint16_t)iport;
919 } else {
920 *host = *host_port;
921 *port = 0;
922 }
923
924 return PJ_SUCCESS;
925 }
926
927 /* Create ICE media transports (when ice is enabled) */
create_ice_media_transport(const pjsua_transport_config * cfg,pjsua_call_media * call_med,pj_bool_t async)928 static pj_status_t create_ice_media_transport(
929 const pjsua_transport_config *cfg,
930 pjsua_call_media *call_med,
931 pj_bool_t async)
932 {
933 char stunip[PJ_INET6_ADDRSTRLEN];
934 pjsua_acc_config *acc_cfg;
935 pj_ice_strans_cfg ice_cfg;
936 pjmedia_ice_cb ice_cb;
937 char name[32];
938 unsigned comp_cnt;
939 pj_status_t status;
940 pj_bool_t use_ipv6, use_nat64;
941 pj_bool_t trickle = PJ_FALSE;
942 pjmedia_sdp_session *rem_sdp;
943
944 acc_cfg = &pjsua_var.acc[call_med->call->acc_id].cfg;
945 use_ipv6 = (acc_cfg->ipv6_media_use != PJSUA_IPV6_DISABLED);
946 use_nat64 = (acc_cfg->nat64_opt != PJSUA_NAT64_DISABLED);
947
948 /* Make sure STUN server resolution has completed */
949 if (pjsua_media_acc_is_using_stun(call_med->call->acc_id)) {
950 pj_bool_t retry_stun = (acc_cfg->media_stun_use &
951 PJSUA_STUN_RETRY_ON_FAILURE) ==
952 PJSUA_STUN_RETRY_ON_FAILURE;
953 status = resolve_stun_server(PJ_TRUE, retry_stun,
954 (unsigned)acc_cfg->nat64_opt);
955 if (status != PJ_SUCCESS) {
956 pjsua_perror(THIS_FILE, "Error resolving STUN server", status);
957 return status;
958 }
959 }
960
961 /* Create ICE stream transport configuration */
962 pj_ice_strans_cfg_default(&ice_cfg);
963 pj_bzero(&ice_cfg.stun, sizeof(ice_cfg.stun));
964 pj_bzero(&ice_cfg.turn, sizeof(ice_cfg.turn));
965 pj_stun_config_init(&ice_cfg.stun_cfg, &pjsua_var.cp.factory, 0,
966 pjsip_endpt_get_ioqueue(pjsua_var.endpt),
967 pjsip_endpt_get_timer_heap(pjsua_var.endpt));
968
969 ice_cfg.resolver = pjsua_var.resolver;
970
971 ice_cfg.opt = acc_cfg->ice_cfg.ice_opt;
972 rem_sdp = call_med->call->async_call.rem_sdp;
973
974 if (rem_sdp) {
975 /* Match the default address family according to the offer */
976 const pj_str_t ID_IP6 = { "IP6", 3};
977 const pjmedia_sdp_media *m;
978 const pjmedia_sdp_conn *c;
979
980 m = rem_sdp->media[call_med->idx];
981 c = m->conn? m->conn : rem_sdp->conn;
982
983 if (pj_stricmp(&c->addr_type, &ID_IP6) == 0)
984 ice_cfg.af = pj_AF_INET6();
985 } else if (use_ipv6 || use_nat64) {
986 ice_cfg.af = pj_AF_INET6();
987 }
988
989 /* Should not wait for ICE STUN/TURN ready when trickle ICE is enabled */
990 if (ice_cfg.opt.trickle != PJ_ICE_SESS_TRICKLE_DISABLED &&
991 (call_med->call->inv == NULL ||
992 call_med->call->inv->state < PJSIP_INV_STATE_CONFIRMED))
993 {
994 if (rem_sdp) {
995 /* As answerer: and when remote signals trickle ICE in SDP */
996 trickle = pjmedia_ice_sdp_has_trickle(rem_sdp, call_med->idx);
997 if (trickle) {
998 call_med->call->trickle_ice.remote_sup = PJ_TRUE;
999 call_med->call->trickle_ice.enabled = PJ_TRUE;
1000 }
1001 } else {
1002 /* As offerer: and when trickle ICE mode is full */
1003 trickle = (ice_cfg.opt.trickle==PJ_ICE_SESS_TRICKLE_FULL);
1004 call_med->call->trickle_ice.enabled = PJ_TRUE;
1005 }
1006
1007 /* Check if trickle ICE can start trickling/sending SIP INFO */
1008 pjsua_ice_check_start_trickling(call_med->call, PJ_FALSE, NULL);
1009 } else {
1010 /* For non-initial INVITE, always use regular ICE */
1011 ice_cfg.opt.trickle = PJ_ICE_SESS_TRICKLE_DISABLED;
1012 }
1013
1014 /* If STUN transport is configured, initialize STUN transport settings */
1015 if ((pj_sockaddr_has_addr(&pjsua_var.stun_srv) &&
1016 pjsua_media_acc_is_using_stun(call_med->call->acc_id)) ||
1017 acc_cfg->ice_cfg.ice_max_host_cands != 0)
1018 {
1019 ice_cfg.stun_tp_cnt = 1;
1020 pj_ice_strans_stun_cfg_default(&ice_cfg.stun_tp[0]);
1021 if (use_nat64) {
1022 ice_cfg.stun_tp[0].af = pj_AF_INET6();
1023 } else if (use_ipv6 && PJ_ICE_MAX_STUN >= 2) {
1024 ice_cfg.stun_tp_cnt = 2;
1025 pj_ice_strans_stun_cfg_default(&ice_cfg.stun_tp[1]);
1026 ice_cfg.stun_tp[1].af = pj_AF_INET6();
1027 }
1028 }
1029
1030 /* Configure STUN transport settings */
1031 if (ice_cfg.stun_tp_cnt) {
1032 unsigned i;
1033
1034 if (pj_sockaddr_has_addr(&pjsua_var.stun_srv)) {
1035 pj_sockaddr_print(&pjsua_var.stun_srv, stunip,
1036 sizeof(stunip), 0);
1037 }
1038
1039 for (i = 0; i < ice_cfg.stun_tp_cnt; ++i) {
1040 pj_str_t IN6_ADDR_ANY = {"0", 1};
1041
1042 /* Configure STUN server */
1043 if (pjsua_media_acc_is_using_stun(call_med->call->acc_id) &&
1044 pj_sockaddr_has_addr(&pjsua_var.stun_srv) &&
1045 pjsua_var.stun_srv.addr.sa_family == ice_cfg.stun_tp[i].af)
1046 {
1047 ice_cfg.stun_tp[i].server = pj_str(stunip);
1048 ice_cfg.stun_tp[i].port = pj_sockaddr_get_port(
1049 &pjsua_var.stun_srv);
1050 }
1051
1052 /* Configure max host candidates */
1053 if (acc_cfg->ice_cfg.ice_max_host_cands >= 0) {
1054 ice_cfg.stun_tp[i].max_host_cands =
1055 acc_cfg->ice_cfg.ice_max_host_cands;
1056 }
1057
1058 /* Configure binding address */
1059 pj_sockaddr_init(ice_cfg.stun_tp[i].af,
1060 &ice_cfg.stun_tp[i].cfg.bound_addr,
1061 (ice_cfg.stun_tp[i].af == pj_AF_INET()?
1062 &cfg->bound_addr: &IN6_ADDR_ANY),
1063 (pj_uint16_t)cfg->port);
1064 ice_cfg.stun_tp[i].cfg.port_range = (pj_uint16_t)cfg->port_range;
1065 if (cfg->port != 0 && ice_cfg.stun_tp[i].cfg.port_range == 0) {
1066 ice_cfg.stun_tp[i].cfg.port_range =
1067 (pj_uint16_t)(pjsua_var.ua_cfg.max_calls * 10);
1068 }
1069
1070 /* Configure QoS setting */
1071 ice_cfg.stun_tp[i].cfg.qos_type = cfg->qos_type;
1072 pj_memcpy(&ice_cfg.stun_tp[i].cfg.qos_params, &cfg->qos_params,
1073 sizeof(cfg->qos_params));
1074
1075 /* Configure max packet size */
1076 ice_cfg.stun_tp[i].cfg.max_pkt_size = PJMEDIA_MAX_MRU;
1077 }
1078 }
1079
1080 /* Configure TURN settings */
1081 if (acc_cfg->turn_cfg.enable_turn) {
1082 unsigned i, idx = 0;
1083
1084 if (use_ipv6 && !use_nat64 && PJ_ICE_MAX_TURN >= 3) {
1085 ice_cfg.turn_tp_cnt = 3;
1086 idx = 1;
1087 } else {
1088 ice_cfg.turn_tp_cnt = 1;
1089 }
1090
1091 for (i = 0; i < ice_cfg.turn_tp_cnt; i++)
1092 pj_ice_strans_turn_cfg_default(&ice_cfg.turn_tp[i]);
1093
1094 if (use_ipv6 || use_nat64) {
1095 if (!use_nat64)
1096 ice_cfg.turn_tp[idx++].af = pj_AF_INET6();
1097
1098 /* Additional candidate: IPv4 relay via IPv6 TURN server */
1099 ice_cfg.turn_tp[idx].af = pj_AF_INET6();
1100 ice_cfg.turn_tp[idx].alloc_param.af = pj_AF_INET();
1101 }
1102
1103 /* Configure TURN server */
1104 status = parse_host_port(&acc_cfg->turn_cfg.turn_server,
1105 &ice_cfg.turn_tp[0].server,
1106 &ice_cfg.turn_tp[0].port);
1107 if (status != PJ_SUCCESS || ice_cfg.turn_tp[0].server.slen == 0) {
1108 PJ_LOG(1,(THIS_FILE, "Invalid TURN server setting"));
1109 return PJ_EINVAL;
1110 }
1111
1112 if (ice_cfg.turn_tp[0].port == 0)
1113 ice_cfg.turn_tp[0].port = 3479;
1114
1115 for (i = 0; i < ice_cfg.turn_tp_cnt; i++) {
1116 pj_str_t IN6_ADDR_ANY = {"0", 1};
1117
1118 /* Configure TURN connection settings and credential */
1119 ice_cfg.turn_tp[i].server = ice_cfg.turn_tp[0].server;
1120 ice_cfg.turn_tp[i].port = ice_cfg.turn_tp[0].port;
1121 ice_cfg.turn_tp[i].conn_type = acc_cfg->turn_cfg.turn_conn_type;
1122 pj_memcpy(&ice_cfg.turn_tp[i].auth_cred,
1123 &acc_cfg->turn_cfg.turn_auth_cred,
1124 sizeof(ice_cfg.turn_tp[i].auth_cred));
1125
1126 /* Configure QoS setting */
1127 ice_cfg.turn_tp[i].cfg.qos_type = cfg->qos_type;
1128 pj_memcpy(&ice_cfg.turn_tp[i].cfg.qos_params, &cfg->qos_params,
1129 sizeof(cfg->qos_params));
1130
1131 /* Configure binding address */
1132 pj_sockaddr_init(ice_cfg.turn_tp[i].af,
1133 &ice_cfg.turn_tp[i].cfg.bound_addr,
1134 (ice_cfg.turn_tp[i].af == pj_AF_INET()?
1135 &cfg->bound_addr: &IN6_ADDR_ANY),
1136 (pj_uint16_t)cfg->port);
1137 ice_cfg.turn_tp[i].cfg.port_range = (pj_uint16_t)cfg->port_range;
1138 if (cfg->port != 0 && ice_cfg.turn_tp[i].cfg.port_range == 0)
1139 ice_cfg.turn_tp[i].cfg.port_range =
1140 (pj_uint16_t)(pjsua_var.ua_cfg.max_calls * 10);
1141
1142 /* Configure max packet size */
1143 ice_cfg.turn_tp[i].cfg.max_pkt_size = PJMEDIA_MAX_MRU;
1144
1145 #if PJ_HAS_SSL_SOCK
1146 if (ice_cfg.turn_tp[i].conn_type == PJ_TURN_TP_TLS) {
1147 pj_memcpy(&ice_cfg.turn_tp[i].cfg.tls_cfg,
1148 &acc_cfg->turn_cfg.turn_tls_setting,
1149 sizeof(ice_cfg.turn_tp[i].cfg.tls_cfg));
1150 }
1151 #endif
1152 }
1153 }
1154
1155 pj_bzero(&ice_cb, sizeof(pjmedia_ice_cb));
1156 ice_cb.on_ice_complete = &on_ice_complete;
1157 pj_ansi_snprintf(name, sizeof(name), "icetp%02d", call_med->idx);
1158 call_med->tp_ready = trickle? PJ_SUCCESS : PJ_EPENDING;
1159
1160 comp_cnt = 1;
1161 if (PJMEDIA_ADVERTISE_RTCP && !acc_cfg->ice_cfg.ice_no_rtcp)
1162 ++comp_cnt;
1163
1164 status = pjmedia_ice_create3(pjsua_var.med_endpt, name, comp_cnt,
1165 &ice_cfg, &ice_cb, PJSUA_ICE_TRANSPORT_OPTION,
1166 call_med, &call_med->tp);
1167 if (status != PJ_SUCCESS) {
1168 pjsua_perror(THIS_FILE, "Unable to create ICE media transport",
1169 status);
1170 goto on_error;
1171 }
1172
1173 /* Wait until transport is initialized, or time out */
1174 if (!async && !trickle) {
1175 pj_bool_t has_pjsua_lock = PJSUA_LOCK_IS_LOCKED();
1176 pjsip_dialog *dlg = call_med->call->inv ?
1177 call_med->call->inv->dlg : NULL;
1178 if (has_pjsua_lock)
1179 PJSUA_UNLOCK();
1180 if (dlg) {
1181 /* Don't lock otherwise deadlock:
1182 * https://trac.pjsip.org/repos/ticket/1737
1183 */
1184 pjsip_dlg_inc_session(dlg, &pjsua_var.mod);
1185 pjsip_dlg_dec_lock(dlg);
1186 }
1187 while (call_med->tp_ready == PJ_EPENDING) {
1188 pjsua_handle_events(100);
1189 }
1190 if (dlg) {
1191 pjsip_dlg_inc_lock(dlg);
1192 pjsip_dlg_dec_session(dlg, &pjsua_var.mod);
1193 }
1194 if (has_pjsua_lock)
1195 PJSUA_LOCK();
1196 }
1197
1198 if (!call_med->tp) {
1199 /* Call has been disconnected, and media transports have been cleared
1200 * (see ticket #1759).
1201 */
1202 PJ_LOG(4,(THIS_FILE, "Media transport initialization cancelled "
1203 "because call has been disconnected"));
1204 status = PJ_ECANCELLED;
1205 goto on_error;
1206 } else if (async && call_med->tp_ready == PJ_EPENDING) {
1207 return PJ_EPENDING;
1208 } else if (call_med->tp_ready != PJ_SUCCESS) {
1209 pjsua_perror(THIS_FILE, "Error initializing ICE media transport",
1210 call_med->tp_ready);
1211 status = call_med->tp_ready;
1212 goto on_error;
1213 }
1214
1215 pjmedia_transport_simulate_lost(call_med->tp, PJMEDIA_DIR_ENCODING,
1216 pjsua_var.media_cfg.tx_drop_pct);
1217
1218 pjmedia_transport_simulate_lost(call_med->tp, PJMEDIA_DIR_DECODING,
1219 pjsua_var.media_cfg.rx_drop_pct);
1220
1221 return PJ_SUCCESS;
1222
1223 on_error:
1224 if (call_med->tp != NULL) {
1225 pjmedia_transport_close(call_med->tp);
1226 call_med->tp = NULL;
1227 }
1228
1229 return status;
1230 }
1231
1232 #if DISABLED_FOR_TICKET_1185
1233 /* Create ICE media transports (when ice is enabled) */
create_ice_media_transports(pjsua_transport_config * cfg)1234 static pj_status_t create_ice_media_transports(pjsua_transport_config *cfg)
1235 {
1236 unsigned i;
1237 pj_status_t status;
1238
1239 for (i=0; i < pjsua_var.ua_cfg.max_calls; ++i) {
1240 pjsua_call *call = &pjsua_var.calls[i];
1241 unsigned strm_idx;
1242
1243 for (strm_idx=0; strm_idx < call->med_cnt; ++strm_idx) {
1244 pjsua_call_media *call_med = &call->media[strm_idx];
1245
1246 status = create_ice_media_transport(cfg, call_med);
1247 if (status != PJ_SUCCESS)
1248 goto on_error;
1249 }
1250 }
1251
1252 return PJ_SUCCESS;
1253
1254 on_error:
1255 for (i=0; i < pjsua_var.ua_cfg.max_calls; ++i) {
1256 pjsua_call *call = &pjsua_var.calls[i];
1257 unsigned strm_idx;
1258
1259 for (strm_idx=0; strm_idx < call->med_cnt; ++strm_idx) {
1260 pjsua_call_media *call_med = &call->media[strm_idx];
1261
1262 if (call_med->tp) {
1263 pjmedia_transport_close(call_med->tp);
1264 call_med->tp = NULL;
1265 }
1266 }
1267 }
1268 return status;
1269 }
1270 #endif
1271
1272 #if DISABLED_FOR_TICKET_1185
1273 /*
1274 * Create media transports for all the calls. This function creates
1275 * one UDP media transport for each call.
1276 */
pjsua_media_transports_create(const pjsua_transport_config * app_cfg)1277 PJ_DEF(pj_status_t) pjsua_media_transports_create(
1278 const pjsua_transport_config *app_cfg)
1279 {
1280 pjsua_transport_config cfg;
1281 unsigned i;
1282 pj_status_t status;
1283
1284
1285 /* Make sure pjsua_init() has been called */
1286 PJ_ASSERT_RETURN(pjsua_var.ua_cfg.max_calls>0, PJ_EINVALIDOP);
1287
1288 PJSUA_LOCK();
1289
1290 /* Delete existing media transports */
1291 for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) {
1292 pjsua_call *call = &pjsua_var.calls[i];
1293 unsigned strm_idx;
1294
1295 for (strm_idx=0; strm_idx < call->med_cnt; ++strm_idx) {
1296 pjsua_call_media *call_med = &call->media[strm_idx];
1297
1298 if (call_med->tp && call_med->tp_auto_del) {
1299 pjmedia_transport_close(call_med->tp);
1300 call_med->tp = NULL;
1301 call_med->tp_orig = NULL;
1302 }
1303 }
1304 }
1305
1306 /* Copy config */
1307 pjsua_transport_config_dup(pjsua_var.pool, &cfg, app_cfg);
1308
1309 /* Create the transports */
1310 if (pjsua_var.ice_cfg.enable_ice) {
1311 status = create_ice_media_transports(&cfg);
1312 } else {
1313 status = create_udp_media_transports(&cfg);
1314 }
1315
1316 /* Set media transport auto_delete to True */
1317 for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) {
1318 pjsua_call *call = &pjsua_var.calls[i];
1319 unsigned strm_idx;
1320
1321 for (strm_idx=0; strm_idx < call->med_cnt; ++strm_idx) {
1322 pjsua_call_media *call_med = &call->media[strm_idx];
1323
1324 call_med->tp_auto_del = PJ_TRUE;
1325 }
1326 }
1327
1328 PJSUA_UNLOCK();
1329
1330 return status;
1331 }
1332
1333 /*
1334 * Attach application's created media transports.
1335 */
pjsua_media_transports_attach(pjsua_media_transport tp[],unsigned count,pj_bool_t auto_delete)1336 PJ_DEF(pj_status_t) pjsua_media_transports_attach(pjsua_media_transport tp[],
1337 unsigned count,
1338 pj_bool_t auto_delete)
1339 {
1340 unsigned i;
1341
1342 PJ_ASSERT_RETURN(tp && count==pjsua_var.ua_cfg.max_calls, PJ_EINVAL);
1343
1344 /* Assign the media transports */
1345 for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) {
1346 pjsua_call *call = &pjsua_var.calls[i];
1347 unsigned strm_idx;
1348
1349 for (strm_idx=0; strm_idx < call->med_cnt; ++strm_idx) {
1350 pjsua_call_media *call_med = &call->media[strm_idx];
1351
1352 if (call_med->tp && call_med->tp_auto_del) {
1353 pjmedia_transport_close(call_med->tp);
1354 call_med->tp = NULL;
1355 call_med->tp_orig = NULL;
1356 }
1357 }
1358
1359 PJ_TODO(remove_pjsua_media_transports_attach);
1360
1361 call->media[0].tp = tp[i].transport;
1362 call->media[0].tp_auto_del = auto_delete;
1363 }
1364
1365 return PJ_SUCCESS;
1366 }
1367 #endif
1368
1369 /* Go through the list of media in the SDP, find acceptable media, and
1370 * sort them based on the below criteria, and store the indexes
1371 * in the specified array. The criteria is as follows:
1372 * 1. enabled, i.e: SDP media port not zero
1373 * 2. transport protocol in the SDP matching account config's
1374 * secure media transport usage (\a use_srtp field).
1375 * 3. active, i.e: SDP media direction is not "inactive"
1376 * 4. media order (according to the SDP).
1377 */
sort_media(const pjmedia_sdp_session * sdp,const pj_str_t * type,pjmedia_srtp_use use_srtp,pj_uint8_t midx[],unsigned * p_count,unsigned * p_total_count)1378 static void sort_media(const pjmedia_sdp_session *sdp,
1379 const pj_str_t *type,
1380 pjmedia_srtp_use use_srtp,
1381 pj_uint8_t midx[],
1382 unsigned *p_count,
1383 unsigned *p_total_count)
1384 {
1385 unsigned i;
1386 unsigned count = 0;
1387 int score[PJSUA_MAX_CALL_MEDIA];
1388
1389 pj_assert(*p_count >= PJSUA_MAX_CALL_MEDIA);
1390 pj_assert(*p_total_count >= PJSUA_MAX_CALL_MEDIA);
1391
1392 *p_count = 0;
1393 *p_total_count = 0;
1394 for (i=0; i<PJSUA_MAX_CALL_MEDIA; ++i)
1395 score[i] = 1;
1396
1397 /* Score each media */
1398 for (i=0; i<sdp->media_count && count<PJSUA_MAX_CALL_MEDIA; ++i) {
1399 const pjmedia_sdp_media *m = sdp->media[i];
1400 const pjmedia_sdp_conn *c;
1401 pj_uint32_t proto;
1402
1403 /* Skip different media */
1404 if (pj_stricmp(&m->desc.media, type) != 0) {
1405 score[count++] = -22000;
1406 continue;
1407 }
1408
1409 c = m->conn? m->conn : sdp->conn;
1410
1411 /* Supported transports */
1412 proto = pjmedia_sdp_transport_get_proto(&m->desc.transport);
1413 if (PJMEDIA_TP_PROTO_HAS_FLAG(proto, PJMEDIA_TP_PROTO_RTP_SAVP))
1414 {
1415 switch (use_srtp) {
1416 case PJMEDIA_SRTP_MANDATORY:
1417 case PJMEDIA_SRTP_OPTIONAL:
1418 ++score[i];
1419 break;
1420 case PJMEDIA_SRTP_DISABLED:
1421 //--score[i];
1422 score[i] -= 5;
1423 break;
1424 }
1425 } else if (PJMEDIA_TP_PROTO_HAS_FLAG(proto, PJMEDIA_TP_PROTO_RTP_AVP))
1426 {
1427 switch (use_srtp) {
1428 case PJMEDIA_SRTP_MANDATORY:
1429 //--score[i];
1430 score[i] -= 5;
1431 break;
1432 case PJMEDIA_SRTP_OPTIONAL:
1433 /* No change in score */
1434 break;
1435 case PJMEDIA_SRTP_DISABLED:
1436 ++score[i];
1437 break;
1438 }
1439 } else {
1440 score[i] -= 10;
1441 }
1442
1443 /* Is media disabled? */
1444 if (m->desc.port == 0)
1445 score[i] -= 10;
1446
1447 /* Is media inactive? */
1448 if (pjmedia_sdp_media_find_attr2(m, "inactive", NULL) ||
1449 pj_strcmp2(&c->addr, "0.0.0.0") == 0)
1450 {
1451 //score[i] -= 10;
1452 score[i] -= 1;
1453 }
1454
1455 ++count;
1456 }
1457
1458 /* Created sorted list based on quality */
1459 for (i=0; i<count; ++i) {
1460 unsigned j;
1461 int best = 0;
1462
1463 for (j=1; j<count; ++j) {
1464 if (score[j] > score[best])
1465 best = j;
1466 }
1467 /* Don't put media with negative score, that media is unacceptable
1468 * for us.
1469 */
1470 midx[i] = (pj_uint8_t)best;
1471 if (score[best] >= 0)
1472 (*p_count)++;
1473 if (score[best] > -22000)
1474 (*p_total_count)++;
1475
1476 score[best] = -22000;
1477
1478 }
1479 }
1480
1481
1482 /* Go through the list of media in the call, find acceptable media, and
1483 * sort them based on the "quality" of the media, and store the indexes
1484 * in the specified array. Media with the best quality will be listed
1485 * first in the array.
1486 */
sort_media2(const pjsua_call_media * call_med,pj_bool_t check_tp,unsigned call_med_cnt,pjmedia_type type,pj_uint8_t midx[],unsigned * p_count,unsigned * p_total_count)1487 static void sort_media2(const pjsua_call_media *call_med,
1488 pj_bool_t check_tp,
1489 unsigned call_med_cnt,
1490 pjmedia_type type,
1491 pj_uint8_t midx[],
1492 unsigned *p_count,
1493 unsigned *p_total_count)
1494 {
1495 unsigned i;
1496 unsigned count = 0;
1497 int score[PJSUA_MAX_CALL_MEDIA];
1498
1499 pj_assert(*p_count >= PJSUA_MAX_CALL_MEDIA);
1500 pj_assert(*p_total_count >= PJSUA_MAX_CALL_MEDIA);
1501
1502 *p_count = 0;
1503 *p_total_count = 0;
1504 for (i=0; i<PJSUA_MAX_CALL_MEDIA; ++i)
1505 score[i] = 1;
1506
1507 /* Score each media */
1508 for (i=0; i<call_med_cnt && count<PJSUA_MAX_CALL_MEDIA; ++i) {
1509
1510 /* Skip different media */
1511 if (call_med[i].type != type) {
1512 score[count++] = -22000;
1513 continue;
1514 }
1515
1516 /* Is it active? */
1517 if (check_tp && !call_med[i].tp) {
1518 score[i] -= 10;
1519 }
1520
1521 ++count;
1522 }
1523
1524 /* Created sorted list based on quality */
1525 for (i=0; i<count; ++i) {
1526 unsigned j;
1527 int best = 0;
1528
1529 for (j=1; j<count; ++j) {
1530 if (score[j] > score[best])
1531 best = j;
1532 }
1533 /* Don't put media with negative score, that media is unacceptable
1534 * for us.
1535 */
1536 midx[i] = (pj_uint8_t)best;
1537 if (score[best] >= 0)
1538 (*p_count)++;
1539 if (score[best] > -22000)
1540 (*p_total_count)++;
1541
1542 score[best] = -22000;
1543
1544 }
1545 }
1546
1547 /* Callback to receive global media events */
on_media_event(pjmedia_event * event,void * user_data)1548 pj_status_t on_media_event(pjmedia_event *event, void *user_data)
1549 {
1550 char ev_name[5];
1551 pj_status_t status = PJ_SUCCESS;
1552
1553 PJ_UNUSED_ARG(user_data);
1554
1555 pjmedia_fourcc_name(event->type, ev_name);
1556 PJ_LOG(4,(THIS_FILE, "Received media event type=%s, src=%p, epub=%p",
1557 ev_name, event->src, event->epub));
1558
1559 /* Forward the event */
1560 if (pjsua_var.ua_cfg.cb.on_media_event) {
1561 (*pjsua_var.ua_cfg.cb.on_media_event)(event);
1562 }
1563
1564 return status;
1565 }
1566
1567 /* Call on_call_media_event() callback using timer */
call_med_event_cb(void * user_data)1568 void call_med_event_cb(void *user_data)
1569 {
1570 pjsua_event_list *eve = (pjsua_event_list *)user_data;
1571
1572 (*pjsua_var.ua_cfg.cb.on_call_media_event)(eve->call_id,
1573 eve->med_idx,
1574 &eve->event);
1575
1576 pj_mutex_lock(pjsua_var.timer_mutex);
1577 pj_list_push_back(&pjsua_var.event_list, eve);
1578 pj_mutex_unlock(pjsua_var.timer_mutex);
1579 }
1580
1581 /* Callback to receive media events of a call */
call_media_on_event(pjmedia_event * event,void * user_data)1582 pj_status_t call_media_on_event(pjmedia_event *event,
1583 void *user_data)
1584 {
1585 pjsua_call_media *call_med = (pjsua_call_media*)user_data;
1586 pjsua_call *call = call_med? call_med->call : NULL;
1587 char ev_name[5];
1588 pj_status_t status = PJ_SUCCESS;
1589
1590 pjmedia_fourcc_name(event->type, ev_name);
1591 PJ_LOG(5,(THIS_FILE, "Call %d: Media %d: Received media event, type=%s, "
1592 "src=%p, epub=%p",
1593 call->index, call_med->idx, ev_name,
1594 event->src, event->epub));
1595
1596 switch(event->type) {
1597 case PJMEDIA_EVENT_KEYFRAME_MISSING:
1598 if (call->opt.req_keyframe_method & PJSUA_VID_REQ_KEYFRAME_SIP_INFO)
1599 {
1600 pj_timestamp now;
1601
1602 pj_get_timestamp(&now);
1603 if (pj_elapsed_msec(&call_med->last_req_keyframe, &now) >=
1604 PJSUA_VID_REQ_KEYFRAME_INTERVAL)
1605 {
1606 pjsua_msg_data msg_data;
1607 const pj_str_t SIP_INFO = {"INFO", 4};
1608 const char *BODY_TYPE = "application/media_control+xml";
1609 const char *BODY =
1610 "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
1611 "<media_control><vc_primitive><to_encoder>"
1612 "<picture_fast_update/>"
1613 "</to_encoder></vc_primitive></media_control>";
1614
1615 PJ_LOG(4,(THIS_FILE,
1616 "Sending video keyframe request via SIP INFO"));
1617
1618 pjsua_msg_data_init(&msg_data);
1619 pj_cstr(&msg_data.content_type, BODY_TYPE);
1620 pj_cstr(&msg_data.msg_body, BODY);
1621 status = pjsua_call_send_request(call->index, &SIP_INFO,
1622 &msg_data);
1623 if (status != PJ_SUCCESS) {
1624 PJ_PERROR(3,(THIS_FILE, status,
1625 "Failed requesting keyframe via SIP INFO"));
1626 } else {
1627 call_med->last_req_keyframe = now;
1628 }
1629 }
1630 }
1631 break;
1632
1633 #if PJSUA_HAS_VIDEO
1634 case PJMEDIA_EVENT_FMT_CHANGED:
1635 if (call_med->strm.v.rdr_win_id != PJSUA_INVALID_ID) {
1636 pjsua_vid_win *w = &pjsua_var.win[call_med->strm.v.rdr_win_id];
1637 if (event->epub == w->vp_rend) {
1638 /* Renderer just changed format, reconnect stream */
1639 pjsua_vid_conf_disconnect(call_med->strm.v.strm_dec_slot,
1640 w->rend_slot);
1641 pjsua_vid_conf_connect(call_med->strm.v.strm_dec_slot,
1642 w->rend_slot, NULL);
1643 }
1644 }
1645
1646 if (call_med->strm.v.strm_dec_slot != PJSUA_INVALID_ID) {
1647 /* Stream decoder changed format, update all conf listeners
1648 * by reconnecting.
1649 */
1650 pjsua_conf_port_id dec_pid = call_med->strm.v.strm_dec_slot;
1651 pjmedia_port *strm_dec;
1652 pjsua_vid_conf_port_info pi;
1653 unsigned i;
1654
1655 status = pjmedia_vid_stream_get_port(call_med->strm.v.stream,
1656 PJMEDIA_DIR_DECODING,
1657 &strm_dec);
1658 if (status != PJ_SUCCESS)
1659 break;
1660
1661 /* Verify that the publisher is the stream decoder */
1662 if (event->epub != strm_dec)
1663 break;
1664
1665 status = pjsua_vid_conf_get_port_info(dec_pid, &pi);
1666 if (status != PJ_SUCCESS)
1667 break;
1668
1669 for (i = 0; i < pi.listener_cnt; i++) {
1670 pjsua_vid_conf_disconnect(dec_pid, pi.listeners[i]);
1671 pjsua_vid_conf_connect(dec_pid, pi.listeners[i], NULL);
1672 }
1673 }
1674 break;
1675
1676 case PJMEDIA_EVENT_VID_DEV_ERROR:
1677 {
1678 PJ_PERROR(3,(THIS_FILE, event->data.vid_dev_err.status,
1679 "Video device id=%d error for call %d",
1680 event->data.vid_dev_err.id,
1681 call->index));
1682 }
1683 break;
1684 #endif
1685
1686 default:
1687 break;
1688 }
1689
1690 if (pjsua_var.ua_cfg.cb.on_call_media_event) {
1691 pjsua_event_list *eve = NULL;
1692
1693 pj_mutex_lock(pjsua_var.timer_mutex);
1694
1695 if (pj_list_empty(&pjsua_var.event_list)) {
1696 eve = PJ_POOL_ALLOC_T(pjsua_var.timer_pool, pjsua_event_list);
1697 } else {
1698 eve = pjsua_var.event_list.next;
1699 pj_list_erase(eve);
1700 }
1701
1702 pj_mutex_unlock(pjsua_var.timer_mutex);
1703
1704 if (call) {
1705 if (call->hanging_up)
1706 return status;
1707
1708 eve->call_id = call->index;
1709 eve->med_idx = call_med->idx;
1710 } else {
1711 /* Also deliver non call events such as audio device error */
1712 eve->call_id = PJSUA_INVALID_ID;
1713 eve->med_idx = 0;
1714 }
1715 pj_memcpy(&eve->event, event, sizeof(pjmedia_event));
1716 pjsua_schedule_timer2(&call_med_event_cb, eve, 1);
1717 }
1718
1719 return status;
1720 }
1721
1722 /* Set media transport state and notify the application via the callback. */
pjsua_set_media_tp_state(pjsua_call_media * call_med,pjsua_med_tp_st tp_st)1723 void pjsua_set_media_tp_state(pjsua_call_media *call_med,
1724 pjsua_med_tp_st tp_st)
1725 {
1726 if (!call_med->call->hanging_up &&
1727 pjsua_var.ua_cfg.cb.on_call_media_transport_state &&
1728 call_med->tp_st != tp_st)
1729 {
1730 pjsua_med_tp_state_info info;
1731
1732 pj_bzero(&info, sizeof(info));
1733 info.med_idx = call_med->idx;
1734 info.state = tp_st;
1735 info.status = call_med->tp_ready;
1736 (*pjsua_var.ua_cfg.cb.on_call_media_transport_state)(
1737 call_med->call->index, &info);
1738 }
1739
1740 call_med->tp_st = tp_st;
1741 }
1742
1743
1744 /* This callback is called when SRTP negotiation completes */
on_srtp_nego_complete(pjmedia_transport * tp,pj_status_t result)1745 static void on_srtp_nego_complete(pjmedia_transport *tp,
1746 pj_status_t result)
1747 {
1748 pjsua_call_media *call_med = (pjsua_call_media*)tp->user_data;
1749 pjsua_call *call;
1750
1751 if (!call_med)
1752 return;
1753
1754 call = call_med->call;
1755 PJ_PERROR(4,(THIS_FILE, result,
1756 "Call %d: Media %d: SRTP negotiation completes",
1757 call->index, call_med->idx));
1758
1759 if (result != PJ_SUCCESS) {
1760 call_med->state = PJSUA_CALL_MEDIA_ERROR;
1761 call_med->dir = PJMEDIA_DIR_NONE;
1762 if (call && !call->hanging_up &&
1763 pjsua_var.ua_cfg.cb.on_call_media_state)
1764 {
1765 /* Defer the callback to a timer */
1766 pjsua_schedule_timer2(&ice_failed_nego_cb,
1767 (void*)(pj_ssize_t)call->index, 1);
1768 }
1769 }
1770 }
1771
1772
1773 /* Callback to resume pjsua_call_media_init() after media transport
1774 * creation is completed.
1775 */
call_media_init_cb(pjsua_call_media * call_med,pj_status_t status,int security_level,int * sip_err_code)1776 static pj_status_t call_media_init_cb(pjsua_call_media *call_med,
1777 pj_status_t status,
1778 int security_level,
1779 int *sip_err_code)
1780 {
1781 pjsua_acc *acc = &pjsua_var.acc[call_med->call->acc_id];
1782 pjmedia_transport_info tpinfo;
1783 int err_code = 0;
1784
1785 if (status != PJ_SUCCESS) {
1786 err_code = PJSIP_SC_TEMPORARILY_UNAVAILABLE;
1787 goto on_return;
1788 }
1789
1790 pjmedia_transport_simulate_lost(call_med->tp, PJMEDIA_DIR_ENCODING,
1791 pjsua_var.media_cfg.tx_drop_pct);
1792
1793 pjmedia_transport_simulate_lost(call_med->tp, PJMEDIA_DIR_DECODING,
1794 pjsua_var.media_cfg.rx_drop_pct);
1795
1796 if (call_med->tp_st == PJSUA_MED_TP_CREATING)
1797 pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_IDLE);
1798
1799 if (!call_med->tp_orig &&
1800 pjsua_var.ua_cfg.cb.on_create_media_transport)
1801 {
1802 call_med->use_custom_med_tp = PJ_TRUE;
1803 } else
1804 call_med->use_custom_med_tp = PJ_FALSE;
1805
1806 #if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
1807 /* This function may be called when SRTP transport already exists
1808 * (e.g: in re-invite, update), don't need to destroy/re-create.
1809 */
1810 if (!call_med->tp_orig) {
1811 pjmedia_srtp_setting srtp_opt;
1812 pjsua_srtp_opt *acc_srtp_opt = &acc->cfg.srtp_opt;
1813 pjmedia_transport *srtp = NULL;
1814 unsigned i;
1815
1816 /* Check if SRTP requires secure signaling */
1817 if (acc->cfg.use_srtp != PJMEDIA_SRTP_DISABLED) {
1818 if (security_level < acc->cfg.srtp_secure_signaling) {
1819 err_code = PJSIP_SC_NOT_ACCEPTABLE;
1820 status = PJSIP_ESESSIONINSECURE;
1821 goto on_return;
1822 }
1823 }
1824
1825 /* Always create SRTP adapter */
1826 pjmedia_srtp_setting_default(&srtp_opt);
1827 srtp_opt.close_member_tp = PJ_TRUE;
1828 srtp_opt.cb.on_srtp_nego_complete = &on_srtp_nego_complete;
1829 srtp_opt.user_data = call_med;
1830
1831 /* Get crypto and keying settings from account settings */
1832 srtp_opt.crypto_count = acc_srtp_opt->crypto_count;
1833 for (i = 0; i < srtp_opt.crypto_count; ++i)
1834 srtp_opt.crypto[i] = acc_srtp_opt->crypto[i];
1835 srtp_opt.keying_count = acc_srtp_opt->keying_count;
1836 for (i = 0; i < srtp_opt.keying_count; ++i)
1837 srtp_opt.keying[i] = acc_srtp_opt->keying[i];
1838
1839 /* If media session has been ever established, let's use remote's
1840 * preference in SRTP usage policy, especially when it is stricter.
1841 */
1842 if (call_med->rem_srtp_use > acc->cfg.use_srtp)
1843 srtp_opt.use = call_med->rem_srtp_use;
1844 else
1845 srtp_opt.use = acc->cfg.use_srtp;
1846
1847 if (pjsua_var.ua_cfg.cb.on_create_media_transport_srtp) {
1848 pjmedia_srtp_setting srtp_opt2 = srtp_opt;
1849 pjsua_call *call = call_med->call;
1850
1851 /* Warn that this callback is deprecated (see also #2100) */
1852 PJ_LOG(1,(THIS_FILE, "Warning: on_create_media_transport_srtp "
1853 "is deprecated and will be removed in the "
1854 "future release"));
1855
1856 (*pjsua_var.ua_cfg.cb.on_create_media_transport_srtp)
1857 (call->index, call_med->idx, &srtp_opt2);
1858
1859 /* Only apply SRTP usage policy if this is initial INVITE */
1860 if (call->inv && call->inv->state < PJSIP_INV_STATE_CONFIRMED) {
1861 srtp_opt.use = srtp_opt2.use;
1862 }
1863
1864 /* Apply crypto and keying settings from callback */
1865 srtp_opt.crypto_count = srtp_opt2.crypto_count;
1866 for (i = 0; i < srtp_opt.crypto_count; ++i)
1867 srtp_opt.crypto[i] = srtp_opt2.crypto[i];
1868 srtp_opt.keying_count = srtp_opt2.keying_count;
1869 for (i = 0; i < srtp_opt.keying_count; ++i)
1870 srtp_opt.keying[i] = srtp_opt2.keying[i];
1871 }
1872
1873 status = pjmedia_transport_srtp_create(pjsua_var.med_endpt,
1874 call_med->tp,
1875 &srtp_opt, &srtp);
1876 if (status != PJ_SUCCESS) {
1877 err_code = PJSIP_SC_INTERNAL_SERVER_ERROR;
1878 goto on_return;
1879 }
1880
1881 /* Set SRTP as current media transport */
1882 call_med->tp_orig = call_med->tp;
1883 call_med->tp = srtp;
1884 }
1885 #else
1886 call_med->tp_orig = call_med->tp;
1887 PJ_UNUSED_ARG(security_level);
1888 #endif
1889
1890
1891 pjmedia_transport_info_init(&tpinfo);
1892 pjmedia_transport_get_info(call_med->tp, &tpinfo);
1893
1894 pj_sockaddr_cp(&call_med->rtp_addr, &tpinfo.sock_info.rtp_addr_name);
1895
1896
1897 on_return:
1898 if (status != PJ_SUCCESS) {
1899 if (call_med->tp) {
1900 pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_NULL);
1901 pjmedia_transport_close(call_med->tp);
1902 call_med->tp = NULL;
1903 }
1904
1905 if (err_code == 0)
1906 err_code = PJSIP_ERRNO_TO_SIP_STATUS(status);
1907
1908 if (sip_err_code)
1909 *sip_err_code = err_code;
1910 }
1911
1912 if (call_med->med_init_cb) {
1913 pjsua_med_tp_state_info info;
1914
1915 pj_bzero(&info, sizeof(info));
1916 info.status = status;
1917 info.state = call_med->tp_st;
1918 info.med_idx = call_med->idx;
1919 info.sip_err_code = err_code;
1920 (*call_med->med_init_cb)(call_med->call->index, &info);
1921 }
1922
1923 return status;
1924 }
1925
1926 /* Determine if call's media is being changed, for example when video is being
1927 * added. Then we can reject incoming re-INVITE, for example. This is the
1928 * solution for https://trac.pjsip.org/repos/ticket/1738
1929 */
pjsua_call_media_is_changing(pjsua_call * call)1930 pj_bool_t pjsua_call_media_is_changing(pjsua_call *call)
1931 {
1932 /* The problem in #1738 occurs because we do handle_events() loop while
1933 * adding media, which could cause incoming re-INVITE to be processed and
1934 * cause havoc. Since the handle_events() loop only happens while adding
1935 * media, it is sufficient to only check if "prov > cnt" for now.
1936 */
1937 return call->med_prov_cnt > call->med_cnt;
1938 }
1939
1940 /* Initialize the media line */
pjsua_call_media_init(pjsua_call_media * call_med,pjmedia_type type,const pjsua_transport_config * tcfg,int security_level,int * sip_err_code,pj_bool_t async,pjsua_med_tp_state_cb cb)1941 pj_status_t pjsua_call_media_init(pjsua_call_media *call_med,
1942 pjmedia_type type,
1943 const pjsua_transport_config *tcfg,
1944 int security_level,
1945 int *sip_err_code,
1946 pj_bool_t async,
1947 pjsua_med_tp_state_cb cb)
1948 {
1949 pj_status_t status = PJ_SUCCESS;
1950
1951 /*
1952 * Note: this function may be called when the media already exists
1953 * (e.g. in reinvites, updates, etc.)
1954 */
1955 call_med->type = type;
1956
1957 /* Create the media transport for initial call. Here are the possible
1958 * media transport state and the action needed:
1959 * - PJSUA_MED_TP_NULL or call_med->tp==NULL, create one.
1960 * - PJSUA_MED_TP_RUNNING, do nothing.
1961 * - PJSUA_MED_TP_DISABLED, re-init (media_create(), etc). Currently,
1962 * this won't happen as media_channel_update() will always clean up
1963 * the unused transport of a disabled media.
1964 */
1965 if (call_med->tp == NULL) {
1966 pjsua_acc *acc = &pjsua_var.acc[call_med->call->acc_id];
1967
1968 /* Initializations. If media transport creation completes immediately,
1969 * we don't need to call the callbacks.
1970 */
1971 call_med->med_init_cb = NULL;
1972 call_med->med_create_cb = NULL;
1973
1974 #if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
1975 /* While in initial call, set default video devices */
1976 if (type == PJMEDIA_TYPE_VIDEO) {
1977 status = pjsua_vid_channel_init(call_med);
1978 if (status != PJ_SUCCESS)
1979 return status;
1980 }
1981 #endif
1982
1983 pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_CREATING);
1984
1985 if (acc->cfg.use_loop_med_tp) {
1986 status = create_loop_media_transport(tcfg, call_med);
1987 } else if (acc->cfg.ice_cfg.enable_ice) {
1988 status = create_ice_media_transport(tcfg, call_med, async);
1989 if (async && status == PJ_EPENDING) {
1990 /* We will resume call media initialization in the
1991 * on_ice_complete() callback.
1992 */
1993 call_med->med_create_cb = &call_media_init_cb;
1994 call_med->med_init_cb = cb;
1995
1996 return PJ_EPENDING;
1997 }
1998 } else {
1999 status = create_udp_media_transport(tcfg, call_med);
2000 }
2001
2002 if (status != PJ_SUCCESS) {
2003 if (sip_err_code)
2004 *sip_err_code = PJSIP_SC_INTERNAL_SERVER_ERROR;
2005 call_med->tp_ready = status;
2006 pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_NULL);
2007 pjsua_perror(THIS_FILE, "Error creating media transport", status);
2008 return status;
2009 }
2010
2011 } else if (call_med->tp_st == PJSUA_MED_TP_DISABLED) {
2012 /* Media is being reenabled. */
2013 //pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_IDLE);
2014
2015 pj_assert(!"Currently no media transport reuse");
2016 }
2017
2018 return call_media_init_cb(call_med, status, security_level,
2019 sip_err_code);
2020 }
2021
2022 /* Callback to resume pjsua_media_channel_init() after media transport
2023 * initialization is completed.
2024 */
media_channel_init_cb(pjsua_call_id call_id,const pjsua_med_tp_state_info * info)2025 static pj_status_t media_channel_init_cb(pjsua_call_id call_id,
2026 const pjsua_med_tp_state_info *info)
2027 {
2028 pjsua_call *call = &pjsua_var.calls[call_id];
2029 pj_status_t status = (info? info->status : PJ_SUCCESS);
2030 unsigned mi;
2031
2032 if (info) {
2033 pj_mutex_lock(call->med_ch_mutex);
2034
2035 /* Set the callback to NULL to indicate that the async operation
2036 * has completed.
2037 */
2038 call->media_prov[info->med_idx].med_init_cb = NULL;
2039
2040 /* In case of failure, save the information to be returned
2041 * by the last media transport to finish.
2042 */
2043 if (info->status != PJ_SUCCESS)
2044 pj_memcpy(&call->med_ch_info, info, sizeof(*info));
2045
2046 /* Check whether all the call's medias have finished calling their
2047 * callbacks.
2048 */
2049 for (mi=0; mi < call->med_prov_cnt; ++mi) {
2050 pjsua_call_media *call_med = &call->media_prov[mi];
2051
2052 if (call_med->med_init_cb) {
2053 pj_mutex_unlock(call->med_ch_mutex);
2054 return PJ_SUCCESS;
2055 }
2056
2057 if (call_med->tp_ready != PJ_SUCCESS)
2058 status = call_med->tp_ready;
2059 }
2060
2061 /* OK, we are called by the last media transport finished. */
2062 pj_mutex_unlock(call->med_ch_mutex);
2063 }
2064
2065 if (call->med_ch_mutex) {
2066 pj_mutex_destroy(call->med_ch_mutex);
2067 call->med_ch_mutex = NULL;
2068 }
2069
2070 PJ_PERROR(5,(THIS_FILE, status,
2071 "Call %d: media transport initialization complete", call_id));
2072
2073 if (status != PJ_SUCCESS) {
2074 if (call->med_ch_info.status == PJ_SUCCESS) {
2075 call->med_ch_info.status = status;
2076 call->med_ch_info.sip_err_code = PJSIP_SC_TEMPORARILY_UNAVAILABLE;
2077 }
2078
2079 /* Revert back provisional media. */
2080 pjsua_media_prov_revert(call_id);
2081
2082 goto on_return;
2083 }
2084
2085 /* Tell the media transport of a new offer/answer session */
2086 for (mi=0; mi < call->med_prov_cnt; ++mi) {
2087 pjsua_call_media *call_med = &call->media_prov[mi];
2088
2089 /* Note: tp may be NULL if this media line is disabled */
2090 if (call_med->tp && call_med->tp_st == PJSUA_MED_TP_IDLE) {
2091 pj_pool_t *tmp_pool = call->async_call.pool_prov;
2092
2093 if (!tmp_pool) {
2094 tmp_pool = (call->inv? call->inv->pool_prov:
2095 call->async_call.dlg->pool);
2096 }
2097
2098 if (call_med->use_custom_med_tp) {
2099 unsigned custom_med_tp_flags = PJSUA_MED_TP_CLOSE_MEMBER;
2100
2101 /* Use custom media transport returned by the application */
2102 call_med->tp =
2103 (*pjsua_var.ua_cfg.cb.on_create_media_transport)
2104 (call_id, mi, call_med->tp,
2105 custom_med_tp_flags);
2106 if (!call_med->tp) {
2107 status =
2108 PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_TEMPORARILY_UNAVAILABLE);
2109 }
2110 }
2111
2112 if (call_med->tp) {
2113 unsigned options = (call_med->enable_rtcp_mux?
2114 PJMEDIA_TPMED_RTCP_MUX: 0);
2115 status = pjmedia_transport_media_create(
2116 call_med->tp, tmp_pool,
2117 options, call->async_call.rem_sdp, mi);
2118 }
2119 if (status != PJ_SUCCESS) {
2120 call->med_ch_info.status = status;
2121 call->med_ch_info.med_idx = mi;
2122 call->med_ch_info.state = call_med->tp_st;
2123 call->med_ch_info.sip_err_code = PJSIP_SC_TEMPORARILY_UNAVAILABLE;
2124
2125 /* Revert back provisional media. */
2126 pjsua_media_prov_revert(call_id);
2127
2128 goto on_return;
2129 }
2130
2131 pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_INIT);
2132 }
2133 }
2134
2135 call->med_ch_info.status = PJ_SUCCESS;
2136
2137 on_return:
2138 if (call->med_ch_cb)
2139 (*call->med_ch_cb)(call->index, &call->med_ch_info);
2140
2141 return status;
2142 }
2143
2144
2145 /* Clean up media transports in provisional media that is not used by
2146 * call media.
2147 */
pjsua_media_prov_clean_up(pjsua_call_id call_id)2148 void pjsua_media_prov_clean_up(pjsua_call_id call_id)
2149 {
2150 pjsua_call *call = &pjsua_var.calls[call_id];
2151 unsigned i;
2152
2153 if (call->med_prov_cnt > call->med_cnt) {
2154 PJ_LOG(4,(THIS_FILE, "Call %d: cleaning up provisional media, "
2155 "prov_med_cnt=%d, med_cnt=%d",
2156 call_id, call->med_prov_cnt, call->med_cnt));
2157 }
2158
2159 for (i = 0; i < call->med_prov_cnt; ++i) {
2160 pjsua_call_media *call_med = &call->media_prov[i];
2161 unsigned j;
2162 pj_bool_t used = PJ_FALSE;
2163
2164 if (call_med->tp == NULL)
2165 continue;
2166
2167 for (j = 0; j < call->med_cnt; ++j) {
2168 if (call->media[j].tp == call_med->tp) {
2169 used = PJ_TRUE;
2170 break;
2171 }
2172 }
2173
2174 if (!used) {
2175 if (call_med->tp_st > PJSUA_MED_TP_IDLE) {
2176 pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_IDLE);
2177 pjmedia_transport_media_stop(call_med->tp);
2178 }
2179 pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_NULL);
2180 pjmedia_transport_close(call_med->tp);
2181 call_med->tp = call_med->tp_orig = NULL;
2182 }
2183 }
2184
2185 // Cleaning up unused media transports should not change provisional
2186 // media count.
2187 //call->med_prov_cnt = 0;
2188 }
2189
2190
2191 /* Revert back provisional media. */
pjsua_media_prov_revert(pjsua_call_id call_id)2192 void pjsua_media_prov_revert(pjsua_call_id call_id)
2193 {
2194 pjsua_call *call = &pjsua_var.calls[call_id];
2195
2196 /* Clean up unused media transport */
2197 pjsua_media_prov_clean_up(call_id);
2198
2199 /* Copy provisional media from active media */
2200 pj_memcpy(call->media_prov, call->media,
2201 sizeof(call->media[0]) * call->med_cnt);
2202 call->med_prov_cnt = call->med_cnt;
2203 }
2204
2205
pjsua_media_channel_init(pjsua_call_id call_id,pjsip_role_e role,int security_level,pj_pool_t * tmp_pool,const pjmedia_sdp_session * rem_sdp,int * sip_err_code,pj_bool_t async,pjsua_med_tp_state_cb cb)2206 pj_status_t pjsua_media_channel_init(pjsua_call_id call_id,
2207 pjsip_role_e role,
2208 int security_level,
2209 pj_pool_t *tmp_pool,
2210 const pjmedia_sdp_session *rem_sdp,
2211 int *sip_err_code,
2212 pj_bool_t async,
2213 pjsua_med_tp_state_cb cb)
2214 {
2215 const pj_str_t STR_AUDIO = { "audio", 5 };
2216 const pj_str_t STR_VIDEO = { "video", 5 };
2217 pjsua_call *call = &pjsua_var.calls[call_id];
2218 pjsua_acc *acc = &pjsua_var.acc[call->acc_id];
2219 pj_uint8_t maudidx[PJSUA_MAX_CALL_MEDIA];
2220 unsigned maudcnt = PJ_ARRAY_SIZE(maudidx);
2221 unsigned mtotaudcnt = PJ_ARRAY_SIZE(maudidx);
2222 pj_uint8_t mvididx[PJSUA_MAX_CALL_MEDIA];
2223 unsigned mvidcnt = PJ_ARRAY_SIZE(mvididx);
2224 unsigned mtotvidcnt = PJ_ARRAY_SIZE(mvididx);
2225 unsigned mi;
2226 pj_bool_t pending_med_tp = PJ_FALSE;
2227 pj_bool_t reinit = PJ_FALSE;
2228 pj_status_t status;
2229
2230 PJ_UNUSED_ARG(role);
2231
2232 /*
2233 * Note: this function may be called when the media already exists
2234 * (e.g. in reinvites, updates, etc).
2235 */
2236
2237 if (pjsua_get_state() != PJSUA_STATE_RUNNING) {
2238 if (sip_err_code)
2239 *sip_err_code = PJSIP_SC_SERVICE_UNAVAILABLE;
2240 return PJ_EBUSY;
2241 }
2242
2243 if (async) {
2244 pj_pool_t *tmppool = (call->inv? call->inv->pool_prov:
2245 call->async_call.dlg->pool);
2246
2247 status = pj_mutex_create_simple(tmppool, NULL, &call->med_ch_mutex);
2248 if (status != PJ_SUCCESS) {
2249 if (sip_err_code)
2250 *sip_err_code = PJSIP_SC_INTERNAL_SERVER_ERROR;
2251 return status;
2252 }
2253 }
2254
2255 if (call->inv && call->inv->state == PJSIP_INV_STATE_CONFIRMED)
2256 reinit = PJ_TRUE;
2257
2258 PJ_LOG(4,(THIS_FILE, "Call %d: %sinitializing media..",
2259 call_id, (reinit?"re-":"") ));
2260
2261 pj_log_push_indent();
2262
2263 /* Init provisional media state */
2264 if (call->med_cnt == 0) {
2265 /* New media session, just copy whole from call media state. */
2266 pj_memcpy(call->media_prov, call->media, sizeof(call->media));
2267 } else {
2268 /* Clean up any unused transports. Note that when local SDP reoffer
2269 * is rejected by remote, there may be any initialized transports that
2270 * are not used by call media and currently there is no notification
2271 * from PJSIP level regarding the reoffer rejection.
2272 */
2273 pjsua_media_prov_clean_up(call_id);
2274
2275 /* Updating media session, copy from call media state. */
2276 pj_memcpy(call->media_prov, call->media,
2277 sizeof(call->media[0]) * call->med_cnt);
2278 }
2279 call->med_prov_cnt = call->med_cnt;
2280
2281 #if DISABLED_FOR_TICKET_1185
2282 /* Return error if media transport has not been created yet
2283 * (e.g. application is starting)
2284 */
2285 for (i=0; i<call->med_cnt; ++i) {
2286 if (call->media[i].tp == NULL) {
2287 status = PJ_EBUSY;
2288 goto on_error;
2289 }
2290 }
2291 #endif
2292
2293 /* Get media count for each media type */
2294 if (rem_sdp) {
2295
2296 /* We are sending answer, check media count for each media type
2297 * from the remote SDP.
2298 */
2299 sort_media(rem_sdp, &STR_AUDIO, acc->cfg.use_srtp,
2300 maudidx, &maudcnt, &mtotaudcnt);
2301
2302 #if PJMEDIA_HAS_VIDEO
2303 sort_media(rem_sdp, &STR_VIDEO, acc->cfg.use_srtp,
2304 mvididx, &mvidcnt, &mtotvidcnt);
2305 #else
2306 mvidcnt = mtotvidcnt = 0;
2307 PJ_UNUSED_ARG(STR_VIDEO);
2308 #endif
2309
2310 if (maudcnt + mvidcnt == 0) {
2311 /* Expecting audio or video in the offer */
2312 if (sip_err_code)
2313 *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE_HERE;
2314 status = PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_NOT_ACCEPTABLE_HERE);
2315 goto on_error;
2316 }
2317
2318 /* Update media count only when remote add any media, this media count
2319 * must never decrease. Also note that we shouldn't apply the media
2320 * count setting (of the call setting) before the SDP negotiation.
2321 */
2322 if (call->med_prov_cnt < rem_sdp->media_count)
2323 call->med_prov_cnt = PJ_MIN(rem_sdp->media_count,
2324 PJSUA_MAX_CALL_MEDIA);
2325
2326 call->rem_offerer = PJ_TRUE;
2327 call->rem_aud_cnt = maudcnt;
2328 call->rem_vid_cnt = mvidcnt;
2329
2330 } else {
2331
2332 /* If call is already established, adjust the existing call media list
2333 * to media count setting in call setting, e.g: re-enable/disable/add
2334 * media from existing media.
2335 * Otherwise, apply media count from the call setting directly.
2336 */
2337 if (reinit) {
2338 pj_bool_t sort_check_tp;
2339
2340 /* Media sorting below will check transport, i.e: media without
2341 * transport will have lower priority. If PJSUA_CALL_REINIT_MEDIA
2342 * is set, we must not check transport.
2343 */
2344 sort_check_tp = !(call->opt.flag & PJSUA_CALL_REINIT_MEDIA);
2345
2346 /* We are sending reoffer, check media count for each media type
2347 * from the existing call media list.
2348 */
2349 sort_media2(call->media_prov, sort_check_tp, call->med_prov_cnt,
2350 PJMEDIA_TYPE_AUDIO, maudidx, &maudcnt, &mtotaudcnt);
2351
2352 /* No need to assert if there's no media. */
2353 //pj_assert(maudcnt > 0);
2354
2355 sort_media2(call->media_prov, sort_check_tp, call->med_prov_cnt,
2356 PJMEDIA_TYPE_VIDEO, mvididx, &mvidcnt, &mtotvidcnt);
2357
2358 /* Call setting may add or remove media. Adding media is done by
2359 * enabling any disabled/port-zeroed media first, then adding new
2360 * media whenever needed. Removing media is done by disabling
2361 * media with the lowest 'quality'.
2362 */
2363
2364 /* Check if we need to add new audio */
2365 if (maudcnt < call->opt.aud_cnt &&
2366 mtotaudcnt < call->opt.aud_cnt)
2367 {
2368 for (mi = 0; mi < call->opt.aud_cnt - mtotaudcnt; ++mi)
2369 maudidx[maudcnt++] = (pj_uint8_t)call->med_prov_cnt++;
2370
2371 mtotaudcnt = call->opt.aud_cnt;
2372 }
2373 maudcnt = call->opt.aud_cnt;
2374
2375 /* Check if we need to add new video */
2376 if (mvidcnt < call->opt.vid_cnt &&
2377 mtotvidcnt < call->opt.vid_cnt)
2378 {
2379 for (mi = 0; mi < call->opt.vid_cnt - mtotvidcnt; ++mi)
2380 mvididx[mvidcnt++] = (pj_uint8_t)call->med_prov_cnt++;
2381
2382 mtotvidcnt = call->opt.vid_cnt;
2383 }
2384 mvidcnt = call->opt.vid_cnt;
2385
2386 /* In case of media reinit, 'med_prov_cnt' may be decreased
2387 * because the new call->opt says so. As media count should
2388 * never decrease, we should verify 'med_prov_cnt' to be
2389 * at least equal to 'med_cnt' (see also #1987).
2390 */
2391 if ((call->opt.flag & PJSUA_CALL_REINIT_MEDIA) &&
2392 call->med_prov_cnt < call->med_cnt)
2393 {
2394 call->med_prov_cnt = call->med_cnt;
2395 }
2396
2397 } else {
2398
2399 maudcnt = mtotaudcnt = call->opt.aud_cnt;
2400 for (mi=0; mi<maudcnt; ++mi) {
2401 maudidx[mi] = (pj_uint8_t)mi;
2402 }
2403 mvidcnt = mtotvidcnt = call->opt.vid_cnt;
2404 for (mi=0; mi<mvidcnt; ++mi) {
2405 mvididx[mi] = (pj_uint8_t)(maudcnt + mi);
2406 }
2407 call->med_prov_cnt = maudcnt + mvidcnt;
2408
2409 /* Need to publish supported media? */
2410 if (call->opt.flag & PJSUA_CALL_INCLUDE_DISABLED_MEDIA) {
2411 if (mtotaudcnt == 0) {
2412 mtotaudcnt = 1;
2413 maudidx[0] = (pj_uint8_t)call->med_prov_cnt++;
2414 }
2415 #if PJMEDIA_HAS_VIDEO
2416 if (mtotvidcnt == 0) {
2417 mtotvidcnt = 1;
2418 mvididx[0] = (pj_uint8_t)call->med_prov_cnt++;
2419 }
2420 #endif
2421 }
2422 }
2423
2424 call->rem_offerer = PJ_FALSE;
2425 }
2426
2427 if (call->med_prov_cnt == 0) {
2428 /* Expecting at least one media */
2429 if (sip_err_code)
2430 *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE_HERE;
2431 status = PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_NOT_ACCEPTABLE_HERE);
2432 goto on_error;
2433 }
2434
2435 if (async) {
2436 call->med_ch_cb = cb;
2437 }
2438
2439 if (rem_sdp) {
2440 call->async_call.rem_sdp =
2441 pjmedia_sdp_session_clone(call->inv->pool_prov, rem_sdp);
2442 } else {
2443 call->async_call.rem_sdp = NULL;
2444 }
2445
2446 call->async_call.pool_prov = tmp_pool;
2447
2448 /* Initialize each media line */
2449 for (mi=0; mi < call->med_prov_cnt; ++mi) {
2450 pjsua_call_media *call_med = &call->media_prov[mi];
2451 pj_bool_t enabled = PJ_FALSE;
2452 pjmedia_type media_type = PJMEDIA_TYPE_UNKNOWN;
2453
2454 if (pj_memchr(maudidx, mi, mtotaudcnt * sizeof(maudidx[0]))) {
2455 media_type = PJMEDIA_TYPE_AUDIO;
2456 if (call->opt.aud_cnt &&
2457 pj_memchr(maudidx, mi, maudcnt * sizeof(maudidx[0])))
2458 {
2459 enabled = PJ_TRUE;
2460 }
2461 } else if (pj_memchr(mvididx, mi, mtotvidcnt * sizeof(mvididx[0]))) {
2462 media_type = PJMEDIA_TYPE_VIDEO;
2463 if (call->opt.vid_cnt &&
2464 pj_memchr(mvididx, mi, mvidcnt * sizeof(mvididx[0])))
2465 {
2466 enabled = PJ_TRUE;
2467 }
2468 }
2469
2470 if (enabled) {
2471 call_med->enable_rtcp_mux = acc->cfg.enable_rtcp_mux;
2472
2473 status = pjsua_call_media_init(call_med, media_type,
2474 &acc->cfg.rtp_cfg,
2475 security_level, sip_err_code,
2476 async,
2477 (async? &media_channel_init_cb:
2478 NULL));
2479 if (status == PJ_EPENDING) {
2480 pending_med_tp = PJ_TRUE;
2481 } else if (status != PJ_SUCCESS) {
2482 if (pending_med_tp) {
2483 /* Save failure information. */
2484 call_med->tp_ready = status;
2485 pj_bzero(&call->med_ch_info, sizeof(call->med_ch_info));
2486 call->med_ch_info.status = status;
2487 call->med_ch_info.state = call_med->tp_st;
2488 call->med_ch_info.med_idx = call_med->idx;
2489 if (sip_err_code)
2490 call->med_ch_info.sip_err_code = *sip_err_code;
2491
2492 /* We will return failure in the callback later. */
2493 return PJ_EPENDING;
2494 }
2495
2496 /* Revert back provisional media. */
2497 pjsua_media_prov_revert(call_id);
2498
2499 goto on_error;
2500 }
2501
2502 /* Find and save "a=mid". Currently this is for trickle ICE.
2503 * Trickle ICE match media in SDP of SIP INFO by comparing this
2504 * attribute, so remote SDP must be received first before remote
2505 * SDP in SIP INFO can be processed.
2506 */
2507 if (rem_sdp && call_med->rem_mid.slen == 0) {
2508 const pjmedia_sdp_media *m = rem_sdp->media[mi];
2509 pjmedia_sdp_attr *a;
2510
2511 a = pjmedia_sdp_media_find_attr2(m, "mid", NULL);
2512 if (a)
2513 call_med->rem_mid = a->value;
2514 }
2515
2516 } else {
2517 /* By convention, the media is disabled if transport is NULL
2518 * or transport state is PJSUA_MED_TP_DISABLED.
2519 */
2520 if (call_med->tp) {
2521 // Don't close transport here, as SDP negotiation has not been
2522 // done and stream may be still active. Once SDP negotiation
2523 // is done (channel_update() invoked), this transport will be
2524 // closed there.
2525 //pjmedia_transport_close(call_med->tp);
2526 //call_med->tp = NULL;
2527 pj_assert(call_med->tp_st == PJSUA_MED_TP_INIT ||
2528 call_med->tp_st == PJSUA_MED_TP_RUNNING);
2529 pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_DISABLED);
2530 }
2531
2532 /* Put media type just for info if not yet defined */
2533 if (call_med->type == PJMEDIA_TYPE_NONE)
2534 call_med->type = media_type;
2535 }
2536 }
2537
2538 if (maudcnt > 0) {
2539 call->audio_idx = maudidx[0];
2540
2541 PJ_LOG(4,(THIS_FILE, "Media index %d selected for audio call %d",
2542 call->audio_idx, call->index));
2543 } else {
2544 call->audio_idx = -1;
2545 }
2546
2547 if (pending_med_tp) {
2548 /* We shouldn't use temporary pool anymore. */
2549 call->async_call.pool_prov = NULL;
2550 /* We have a pending media transport initialization. */
2551 pj_log_pop_indent();
2552 return PJ_EPENDING;
2553 }
2554
2555 /* Media transport initialization completed immediately, so
2556 * we don't need to call the callback.
2557 */
2558 call->med_ch_cb = NULL;
2559
2560 status = media_channel_init_cb(call_id, NULL);
2561 if (status != PJ_SUCCESS && sip_err_code) {
2562 if (call->med_ch_info.sip_err_code)
2563 *sip_err_code = call->med_ch_info.sip_err_code;
2564 else
2565 *sip_err_code = PJSIP_ERRNO_TO_SIP_STATUS(status);
2566 }
2567
2568 pj_log_pop_indent();
2569 return status;
2570
2571 on_error:
2572 if (call->med_ch_mutex) {
2573 pj_mutex_destroy(call->med_ch_mutex);
2574 call->med_ch_mutex = NULL;
2575 }
2576
2577 if (sip_err_code && *sip_err_code == 0)
2578 *sip_err_code = PJSIP_ERRNO_TO_SIP_STATUS(status);
2579
2580 pj_log_pop_indent();
2581 return status;
2582 }
2583
2584
2585 /* Create SDP based on the current media channel. Note that, this function
2586 * will not modify the media channel, so when receiving new offer or
2587 * updating media count (via call setting), media channel must be reinit'd
2588 * (using pjsua_media_channel_init()) first before calling this function.
2589 */
pjsua_media_channel_create_sdp(pjsua_call_id call_id,pj_pool_t * pool,const pjmedia_sdp_session * rem_sdp,pjmedia_sdp_session ** p_sdp,int * sip_err_code)2590 pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id,
2591 pj_pool_t *pool,
2592 const pjmedia_sdp_session *rem_sdp,
2593 pjmedia_sdp_session **p_sdp,
2594 int *sip_err_code)
2595 {
2596 enum { MAX_MEDIA = PJSUA_MAX_CALL_MEDIA };
2597 pjmedia_sdp_session *sdp;
2598 pj_sockaddr origin;
2599 pjsua_call *call = &pjsua_var.calls[call_id];
2600 pjsua_acc *acc = &pjsua_var.acc[call->acc_id];
2601 pjmedia_sdp_neg_state sdp_neg_state = PJMEDIA_SDP_NEG_STATE_NULL;
2602 unsigned mi;
2603 unsigned tot_bandw_tias = 0;
2604 pj_status_t status;
2605
2606 if (pjsua_get_state() != PJSUA_STATE_RUNNING) {
2607 status = PJ_EBUSY;
2608 goto on_error;
2609 }
2610
2611 #if 0
2612 // This function should not really change the media channel.
2613 if (rem_sdp) {
2614 /* If this is a re-offer, let's re-initialize media as remote may
2615 * add or remove media
2616 */
2617 if (call->inv && call->inv->state == PJSIP_INV_STATE_CONFIRMED) {
2618 status = pjsua_media_channel_init(call_id, PJSIP_ROLE_UAS,
2619 call->secure_level, pool,
2620 rem_sdp, sip_err_code,
2621 PJ_FALSE, NULL);
2622 if (status != PJ_SUCCESS)
2623 return status;
2624 }
2625 } else {
2626 /* Audio is first in our offer, by convention */
2627 // The audio_idx should not be changed here, as this function may be
2628 // called in generating re-offer and the current active audio index
2629 // can be anywhere.
2630 //call->audio_idx = 0;
2631 }
2632 #endif
2633
2634 #if 0
2635 // Since r3512, old-style hold should have got transport, created by
2636 // pjsua_media_channel_init() in initial offer/answer or remote reoffer.
2637 /* Create media if it's not created. This could happen when call is
2638 * currently on-hold (with the old style hold)
2639 */
2640 if (call->media[call->audio_idx].tp == NULL) {
2641 pjsip_role_e role;
2642 role = (rem_sdp ? PJSIP_ROLE_UAS : PJSIP_ROLE_UAC);
2643 status = pjsua_media_channel_init(call_id, role, call->secure_level,
2644 pool, rem_sdp, sip_err_code);
2645 if (status != PJ_SUCCESS)
2646 return status;
2647 }
2648 #endif
2649
2650 /* Get SDP negotiator state */
2651 if (call->inv && call->inv->neg)
2652 sdp_neg_state = pjmedia_sdp_neg_get_state(call->inv->neg);
2653
2654 PJ_UNUSED_ARG(sdp_neg_state);
2655
2656 /* Get one address to use in the origin field */
2657 pj_bzero(&origin, sizeof(origin));
2658 for (mi=0; mi<call->med_prov_cnt; ++mi) {
2659 pjmedia_transport_info tpinfo;
2660
2661 if (call->media_prov[mi].tp == NULL)
2662 continue;
2663
2664 pjmedia_transport_info_init(&tpinfo);
2665 pjmedia_transport_get_info(call->media_prov[mi].tp, &tpinfo);
2666 pj_sockaddr_cp(&origin, &tpinfo.sock_info.rtp_addr_name);
2667 break;
2668 }
2669
2670 /* Create the base (blank) SDP */
2671 status = pjmedia_endpt_create_base_sdp(pjsua_var.med_endpt, pool, NULL,
2672 &origin, &sdp);
2673 if (status != PJ_SUCCESS)
2674 goto on_error;
2675
2676 /* Process each media line */
2677 for (mi=0; mi<call->med_prov_cnt; ++mi) {
2678 pjsua_call_media *call_med = &call->media_prov[mi];
2679 pjmedia_sdp_media *m = NULL;
2680 pjmedia_transport_info tpinfo;
2681 unsigned i;
2682
2683 if (rem_sdp && mi >= rem_sdp->media_count) {
2684 /* Remote might have removed some media lines. */
2685 /* Note that we must not modify the current active media
2686 * (e.g: stop stream, close/cleanup media transport), as if
2687 * SDP nego fails, the current active media should be maintained.
2688 * Also note that our media count should never decrease, even when
2689 * remote removed some media lines.
2690 */
2691 break;
2692 }
2693
2694 if (call_med->tp == NULL || call_med->tp_st == PJSUA_MED_TP_DISABLED)
2695 {
2696 /*
2697 * This media is disabled. Just create a valid SDP with zero
2698 * port.
2699 */
2700 if (rem_sdp) {
2701 /* Just clone the remote media and deactivate it */
2702 m = pjmedia_sdp_media_clone_deactivate(pool,
2703 rem_sdp->media[mi]);
2704 } else {
2705 m = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_media);
2706 m->desc.transport = pj_str("RTP/AVP");
2707 m->desc.fmt_count = 1;
2708
2709 switch (call_med->type) {
2710 case PJMEDIA_TYPE_AUDIO:
2711 m->desc.media = pj_str("audio");
2712 m->desc.fmt[0] = pj_str("0");
2713 break;
2714 case PJMEDIA_TYPE_VIDEO:
2715 m->desc.media = pj_str("video");
2716 m->desc.fmt[0] = pj_str("31");
2717 break;
2718 default:
2719 /* This must be us generating re-offer, and some unknown
2720 * media may exist, so just clone from active local SDP
2721 * (and it should have been deactivated already).
2722 */
2723 pj_assert(call->inv && call->inv->neg &&
2724 sdp_neg_state == PJMEDIA_SDP_NEG_STATE_DONE);
2725 {
2726 const pjmedia_sdp_session *s_;
2727 pjmedia_sdp_neg_get_active_local(call->inv->neg, &s_);
2728
2729 if (mi < s_->media_count) {
2730 m = pjmedia_sdp_media_clone(pool, s_->media[mi]);
2731 m->desc.port = 0;
2732 } else {
2733 /* Remote may have removed some media lines in
2734 * previous negotiations. However, since our
2735 * media count may never decrease (as per
2736 * the RFC), we'll just offer unknown media here.
2737 */
2738 m->desc.media = pj_str("unknown");
2739 m->desc.fmt[0] = pj_str("0");
2740 }
2741 }
2742 break;
2743 }
2744 }
2745
2746 /* Add connection line, if none */
2747 if (m->conn == NULL && sdp->conn == NULL) {
2748 pj_bool_t use_ipv6;
2749 pj_bool_t use_nat64;
2750
2751 use_ipv6 = (pjsua_var.acc[call->acc_id].cfg.ipv6_media_use !=
2752 PJSUA_IPV6_DISABLED);
2753 use_nat64 = (pjsua_var.acc[call->acc_id].cfg.nat64_opt !=
2754 PJSUA_NAT64_DISABLED);
2755
2756 m->conn = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_conn);
2757 m->conn->net_type = pj_str("IN");
2758 if (use_ipv6 && !use_nat64) {
2759 m->conn->addr_type = pj_str("IP6");
2760 m->conn->addr = pj_str("::1");
2761 } else {
2762 m->conn->addr_type = pj_str("IP4");
2763 m->conn->addr = pj_str("127.0.0.1");
2764 }
2765 }
2766
2767 sdp->media[sdp->media_count++] = m;
2768 continue;
2769 }
2770
2771 /* Get transport address info */
2772 pjmedia_transport_info_init(&tpinfo);
2773 pjmedia_transport_get_info(call_med->tp, &tpinfo);
2774
2775 /* Ask pjmedia endpoint to create SDP media line */
2776 switch (call_med->type) {
2777 case PJMEDIA_TYPE_AUDIO:
2778 status = pjmedia_endpt_create_audio_sdp(pjsua_var.med_endpt, pool,
2779 &tpinfo.sock_info, 0, &m);
2780 break;
2781 #if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
2782 case PJMEDIA_TYPE_VIDEO:
2783 status = pjmedia_endpt_create_video_sdp(pjsua_var.med_endpt, pool,
2784 &tpinfo.sock_info, 0, &m);
2785 break;
2786 #endif
2787 default:
2788 pj_assert(!"Invalid call_med media type");
2789 status = PJ_EBUG;
2790 }
2791
2792 if (status != PJ_SUCCESS)
2793 goto on_error;
2794
2795 /* Add generated media to SDP session */
2796 sdp->media[sdp->media_count++] = m;
2797
2798 /* Disable media if it has zero format/codec */
2799 if (m->desc.fmt_count == 0) {
2800 m->desc.fmt[m->desc.fmt_count++] = pj_str("0");
2801 pjmedia_sdp_media_deactivate(pool, m);
2802 PJ_LOG(3,(THIS_FILE,
2803 "Call %d media %d: Disabled due to no active codec",
2804 call_id, mi));
2805 continue;
2806 }
2807
2808 /* Add ssrc and cname attribute */
2809 m->attr[m->attr_count++] = pjmedia_sdp_attr_create_ssrc(pool,
2810 call_med->ssrc,
2811 &call->cname);
2812
2813 /* Give to transport */
2814 status = pjmedia_transport_encode_sdp(call_med->tp, pool,
2815 sdp, rem_sdp, mi);
2816 if (status != PJ_SUCCESS) {
2817 if (sip_err_code) *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE;
2818 goto on_error;
2819 }
2820
2821 #if PJSUA_SDP_SESS_HAS_CONN
2822 /* Copy c= line of the first media to session level,
2823 * if there's none.
2824 */
2825 if (sdp->conn == NULL) {
2826 sdp->conn = pjmedia_sdp_conn_clone(pool, m->conn);
2827 }
2828 #endif
2829
2830
2831 /* Find media bandwidth info */
2832 for (i = 0; i < m->bandw_count; ++i) {
2833 const pj_str_t STR_BANDW_MODIFIER_TIAS = { "TIAS", 4 };
2834 if (!pj_stricmp(&m->bandw[i]->modifier, &STR_BANDW_MODIFIER_TIAS))
2835 {
2836 tot_bandw_tias += m->bandw[i]->value;
2837 break;
2838 }
2839 }
2840
2841 /* Setup RTCP-FB */
2842 {
2843 pjmedia_rtcp_fb_setting rtcp_cfg;
2844 pjmedia_rtcp_fb_setting_default(&rtcp_cfg);
2845
2846 /* Add RTCP-FB PLI if PJSUA_VID_REQ_KEYFRAME_RTCP_PLI is set */
2847 if (call_med->type == PJMEDIA_TYPE_VIDEO &&
2848 (call->opt.req_keyframe_method &
2849 PJSUA_VID_REQ_KEYFRAME_RTCP_PLI))
2850 {
2851 rtcp_cfg.cap_count = 1;
2852 pj_strset2(&rtcp_cfg.caps[0].codec_id, (char*)"*");
2853 rtcp_cfg.caps[0].type = PJMEDIA_RTCP_FB_NACK;
2854 pj_strset2(&rtcp_cfg.caps[0].param, (char*)"pli");
2855 }
2856
2857 /* Should we put "RTP/AVPF" in SDP?*/
2858 if (rem_sdp) {
2859 /* For answer, match remote offer */
2860 unsigned rem_proto = 0;
2861 rem_proto = pjmedia_sdp_transport_get_proto(
2862 &rem_sdp->media[mi]->desc.transport);
2863 rtcp_cfg.dont_use_avpf =
2864 !PJMEDIA_TP_PROTO_HAS_FLAG(rem_proto,
2865 PJMEDIA_TP_PROFILE_RTCP_FB);
2866 } else {
2867 /* For offer, check account setting */
2868 rtcp_cfg.dont_use_avpf = acc->cfg.rtcp_fb_cfg.dont_use_avpf ||
2869 (acc->cfg.rtcp_fb_cfg.cap_count == 0
2870 && rtcp_cfg.cap_count == 0);
2871 }
2872
2873 status = pjmedia_rtcp_fb_encode_sdp(pool, pjsua_var.med_endpt,
2874 &rtcp_cfg, sdp,
2875 mi, rem_sdp);
2876 if (status != PJ_SUCCESS) {
2877 PJ_PERROR(3,(THIS_FILE, status,
2878 "Call %d media %d: Failed to encode RTCP-FB PLI "
2879 "setting to SDP",
2880 call_id, mi));
2881 }
2882
2883 /* Add any other RTCP-FB setting configured in account setting */
2884 if (acc->cfg.rtcp_fb_cfg.cap_count) {
2885 pj_bool_t tmp = rtcp_cfg.dont_use_avpf;
2886 rtcp_cfg = acc->cfg.rtcp_fb_cfg;
2887 rtcp_cfg.dont_use_avpf = tmp;
2888 status = pjmedia_rtcp_fb_encode_sdp(pool, pjsua_var.med_endpt,
2889 &rtcp_cfg, sdp,
2890 mi, rem_sdp);
2891 if (status != PJ_SUCCESS) {
2892 PJ_PERROR(3,(THIS_FILE, status,
2893 "Call %d media %d: Failed to encode account "
2894 "RTCP-FB setting to SDP",
2895 call_id, mi));
2896 }
2897 }
2898 }
2899
2900 /* Find and save "a=mid". Currently this is for trickle ICE. Trickle
2901 * ICE match media in SDP of SIP INFO by comparing this attribute,
2902 * so remote SDP must be received first before remote SDP in SIP INFO
2903 * can be processed.
2904 */
2905 if (call_med->rem_mid.slen == 0) {
2906 pjmedia_sdp_attr *a;
2907
2908 a = pjmedia_sdp_media_find_attr2(m, "mid", NULL);
2909 if (a)
2910 call_med->rem_mid = a->value;
2911 }
2912 }
2913
2914 /* Add NAT info in the SDP */
2915 if (pjsua_var.ua_cfg.nat_type_in_sdp) {
2916 pjmedia_sdp_attr *a;
2917 pj_str_t value;
2918 char nat_info[80];
2919
2920 value.ptr = nat_info;
2921 if (pjsua_var.ua_cfg.nat_type_in_sdp == 1) {
2922 value.slen = pj_ansi_snprintf(nat_info, sizeof(nat_info),
2923 "%d", pjsua_var.nat_type);
2924 } else {
2925 const char *type_name = pj_stun_get_nat_name(pjsua_var.nat_type);
2926 value.slen = pj_ansi_snprintf(nat_info, sizeof(nat_info),
2927 "%d %s",
2928 pjsua_var.nat_type,
2929 type_name);
2930 }
2931
2932 a = pjmedia_sdp_attr_create(pool, "X-nat", &value);
2933
2934 pjmedia_sdp_attr_add(&sdp->attr_count, sdp->attr, a);
2935
2936 }
2937
2938
2939 /* Add bandwidth info in session level using bandwidth modifier "AS". */
2940 if (tot_bandw_tias) {
2941 unsigned bandw;
2942 const pj_str_t STR_BANDW_MODIFIER_AS = { "AS", 2 };
2943 pjmedia_sdp_bandw *b;
2944
2945 /* AS bandwidth = RTP bitrate + RTCP bitrate.
2946 * RTP bitrate = payload bitrate (total TIAS) + overheads (~16kbps).
2947 * RTCP bitrate = est. 5% of RTP bitrate.
2948 * Note that AS bandwidth is in kbps.
2949 */
2950 bandw = tot_bandw_tias + 16000;
2951 bandw += bandw * 5 / 100;
2952 b = PJ_POOL_ALLOC_T(pool, pjmedia_sdp_bandw);
2953 b->modifier = STR_BANDW_MODIFIER_AS;
2954 b->value = bandw / 1000;
2955 sdp->bandw[sdp->bandw_count++] = b;
2956 }
2957
2958 #if DISABLED_FOR_TICKET_1185 && defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
2959 /* Check if SRTP is in optional mode and configured to use duplicated
2960 * media, i.e: secured and unsecured version, in the SDP offer.
2961 */
2962 if (!rem_sdp &&
2963 pjsua_var.acc[call->acc_id].cfg.use_srtp == PJMEDIA_SRTP_OPTIONAL &&
2964 pjsua_var.acc[call->acc_id].cfg.srtp_optional_dup_offer)
2965 {
2966 unsigned i;
2967
2968 for (i = 0; i < sdp->media_count; ++i) {
2969 pjmedia_sdp_media *m = sdp->media[i];
2970
2971 /* Check if this media is unsecured but has SDP "crypto"
2972 * attribute.
2973 */
2974 if (pj_stricmp2(&m->desc.transport, "RTP/AVP") == 0 &&
2975 pjmedia_sdp_media_find_attr2(m, "crypto", NULL) != NULL)
2976 {
2977 if (i == (unsigned)call->audio_idx &&
2978 sdp_neg_state == PJMEDIA_SDP_NEG_STATE_DONE)
2979 {
2980 /* This is a session update, and peer has chosen the
2981 * unsecured version, so let's make this unsecured too.
2982 */
2983 pjmedia_sdp_media_remove_all_attr(m, "crypto");
2984 } else {
2985 /* This is new offer, duplicate media so we'll have
2986 * secured (with "RTP/SAVP" transport) and and unsecured
2987 * versions.
2988 */
2989 pjmedia_sdp_media *new_m;
2990
2991 /* Duplicate this media and apply secured transport */
2992 new_m = pjmedia_sdp_media_clone(pool, m);
2993 pj_strdup2(pool, &new_m->desc.transport, "RTP/SAVP");
2994
2995 /* Remove the "crypto" attribute in the unsecured media */
2996 pjmedia_sdp_media_remove_all_attr(m, "crypto");
2997
2998 /* Insert the new media before the unsecured media */
2999 if (sdp->media_count < PJMEDIA_MAX_SDP_MEDIA) {
3000 pj_array_insert(sdp->media, sizeof(new_m),
3001 sdp->media_count, i, &new_m);
3002 ++sdp->media_count;
3003 ++i;
3004 }
3005 }
3006 }
3007 }
3008 }
3009 #endif
3010
3011 call->rem_offerer = (rem_sdp != NULL);
3012
3013 /* Notify application */
3014 if (!call->hanging_up && pjsua_var.ua_cfg.cb.on_call_sdp_created) {
3015 (*pjsua_var.ua_cfg.cb.on_call_sdp_created)(call_id, sdp,
3016 pool, rem_sdp);
3017 }
3018
3019 *p_sdp = sdp;
3020 return PJ_SUCCESS;
3021
3022 on_error:
3023 if (sip_err_code && *sip_err_code == 0)
3024 *sip_err_code = PJSIP_SC_INTERNAL_SERVER_ERROR;
3025
3026 return status;
3027 }
3028
3029
stop_media_stream(pjsua_call * call,unsigned med_idx)3030 static void stop_media_stream(pjsua_call *call, unsigned med_idx)
3031 {
3032 pjsua_call_media *call_med;
3033
3034 if (pjsua_call_media_is_changing(call)) {
3035 call_med = &call->media_prov[med_idx];
3036 if (med_idx >= call->med_prov_cnt)
3037 return;
3038 } else {
3039 call_med = &call->media[med_idx];
3040 if (med_idx >= call->med_cnt)
3041 return;
3042 }
3043
3044 pj_log_push_indent();
3045
3046 if (call_med->type == PJMEDIA_TYPE_AUDIO) {
3047 pjsua_aud_stop_stream(call_med);
3048 }
3049
3050 #if PJMEDIA_HAS_VIDEO
3051 else if (call_med->type == PJMEDIA_TYPE_VIDEO) {
3052 pjsua_vid_stop_stream(call_med);
3053 }
3054 #endif
3055
3056 PJ_LOG(4,(THIS_FILE, "Media stream call%02d:%d is destroyed",
3057 call->index, med_idx));
3058 call_med->prev_state = call_med->state;
3059 call_med->state = PJSUA_CALL_MEDIA_NONE;
3060
3061 /* Try to sync recent changes to provisional media */
3062 if (med_idx < call->med_prov_cnt &&
3063 call->media_prov[med_idx].tp == call_med->tp)
3064 {
3065 pjsua_call_media *prov_med = &call->media_prov[med_idx];
3066
3067 /* Media state */
3068 prov_med->prev_state = call_med->prev_state;
3069 prov_med->state = call_med->state;
3070
3071 /* RTP seq/ts */
3072 prov_med->rtp_tx_seq_ts_set = call_med->rtp_tx_seq_ts_set;
3073 prov_med->rtp_tx_seq = call_med->rtp_tx_seq;
3074 prov_med->rtp_tx_ts = call_med->rtp_tx_ts;
3075
3076 /* Stream */
3077 if (call_med->type == PJMEDIA_TYPE_AUDIO) {
3078 prov_med->strm.a.conf_slot = call_med->strm.a.conf_slot;
3079 prov_med->strm.a.stream = call_med->strm.a.stream;
3080 }
3081 #if PJMEDIA_HAS_VIDEO
3082 else if (call_med->type == PJMEDIA_TYPE_VIDEO) {
3083 prov_med->strm.v.cap_win_id = call_med->strm.v.cap_win_id;
3084 prov_med->strm.v.rdr_win_id = call_med->strm.v.rdr_win_id;
3085 prov_med->strm.v.stream = call_med->strm.v.stream;
3086 }
3087 #endif
3088 }
3089
3090 pj_log_pop_indent();
3091 }
3092
stop_media_session(pjsua_call_id call_id)3093 static void stop_media_session(pjsua_call_id call_id)
3094 {
3095 pjsua_call *call = &pjsua_var.calls[call_id];
3096 unsigned mi;
3097
3098 for (mi=0; mi<call->med_cnt; ++mi) {
3099 stop_media_stream(call, mi);
3100 }
3101 }
3102
pjsua_media_channel_deinit(pjsua_call_id call_id)3103 pj_status_t pjsua_media_channel_deinit(pjsua_call_id call_id)
3104 {
3105 pjsua_call *call = &pjsua_var.calls[call_id];
3106 unsigned mi;
3107
3108 for (mi=0; mi<call->med_cnt; ++mi) {
3109 pjsua_call_media *call_med = &call->media[mi];
3110
3111 if (call_med->tp_st == PJSUA_MED_TP_CREATING) {
3112 /* We will do the deinitialization after media transport
3113 * creation is completed.
3114 */
3115 call->async_call.med_ch_deinit = PJ_TRUE;
3116 return PJ_SUCCESS;
3117 }
3118 }
3119
3120 PJ_LOG(4,(THIS_FILE, "Call %d: deinitializing media..", call_id));
3121 pj_log_push_indent();
3122
3123 stop_media_session(call_id);
3124
3125 /* Stop trickle ICE timer */
3126 if (call->trickle_ice.trickling > PJSUA_OP_STATE_NULL) {
3127 call->trickle_ice.trickling = PJSUA_OP_STATE_NULL;
3128 pjsua_cancel_timer(&call->trickle_ice.timer);
3129 }
3130 call->trickle_ice.enabled = PJ_FALSE;
3131 call->trickle_ice.pending_info = PJ_FALSE;
3132 call->trickle_ice.remote_sup = PJ_FALSE;
3133 call->trickle_ice.retrans18x_count = 0;
3134
3135 /* Clean up media transports */
3136 pjsua_media_prov_clean_up(call_id);
3137 call->med_prov_cnt = 0;
3138 for (mi=0; mi<call->med_cnt; ++mi) {
3139 pjsua_call_media *call_med = &call->media[mi];
3140
3141 if (call_med->tp_st > PJSUA_MED_TP_IDLE) {
3142 pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_IDLE);
3143 pjmedia_transport_media_stop(call_med->tp);
3144 }
3145
3146 if (call_med->tp) {
3147 pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_NULL);
3148 pjmedia_transport_close(call_med->tp);
3149 call_med->tp = call_med->tp_orig = NULL;
3150 }
3151 call_med->tp_orig = NULL;
3152 call_med->rem_srtp_use = PJMEDIA_SRTP_UNKNOWN;
3153 }
3154
3155 pj_log_pop_indent();
3156
3157 return PJ_SUCCESS;
3158 }
3159
3160
3161 /* Match codec fmtp. This will compare the values and the order. */
match_codec_fmtp(const pjmedia_codec_fmtp * fmtp1,const pjmedia_codec_fmtp * fmtp2)3162 static pj_bool_t match_codec_fmtp(const pjmedia_codec_fmtp *fmtp1,
3163 const pjmedia_codec_fmtp *fmtp2)
3164 {
3165 unsigned i;
3166
3167 if (fmtp1->cnt != fmtp2->cnt)
3168 return PJ_FALSE;
3169
3170 for (i = 0; i < fmtp1->cnt; ++i) {
3171 if (pj_stricmp(&fmtp1->param[i].name, &fmtp2->param[i].name))
3172 return PJ_FALSE;
3173 if (pj_stricmp(&fmtp1->param[i].val, &fmtp2->param[i].val))
3174 return PJ_FALSE;
3175 }
3176
3177 return PJ_TRUE;
3178 }
3179
3180 #if PJSUA_MEDIA_HAS_PJMEDIA || PJSUA_THIRD_PARTY_STREAM_HAS_GET_INFO
3181
is_ice_running(pjmedia_transport * tp)3182 static pj_bool_t is_ice_running(pjmedia_transport *tp)
3183 {
3184 pjmedia_transport_info tpinfo;
3185 pjmedia_ice_transport_info *ice_info;
3186
3187 pjmedia_transport_info_init(&tpinfo);
3188 pjmedia_transport_get_info(tp, &tpinfo);
3189 ice_info = (pjmedia_ice_transport_info*)
3190 pjmedia_transport_info_get_spc_info(&tpinfo,
3191 PJMEDIA_TRANSPORT_TYPE_ICE);
3192 return (ice_info && ice_info->sess_state == PJ_ICE_STRANS_STATE_RUNNING);
3193 }
3194
3195
is_media_changed(const pjsua_call * call,unsigned med_idx,const pjsua_stream_info * new_si_)3196 static pj_bool_t is_media_changed(const pjsua_call *call,
3197 unsigned med_idx,
3198 const pjsua_stream_info *new_si_)
3199 {
3200 const pjsua_call_media *call_med = &call->media[med_idx];
3201
3202 /* Check for newly added media */
3203 if (med_idx >= call->med_cnt)
3204 return PJ_TRUE;
3205
3206 /* Compare media type */
3207 if (call_med->type != new_si_->type)
3208 return PJ_TRUE;
3209
3210 /* Audio update checks */
3211 if (call_med->type == PJMEDIA_TYPE_AUDIO) {
3212 pjmedia_stream_info the_old_si;
3213 const pjmedia_stream_info *old_si = NULL;
3214 const pjmedia_stream_info *new_si = &new_si_->info.aud;
3215 const pjmedia_codec_info *old_ci = NULL;
3216 const pjmedia_codec_info *new_ci = &new_si->fmt;
3217 const pjmedia_codec_param *old_cp = NULL;
3218 const pjmedia_codec_param *new_cp = new_si->param;
3219
3220 /* Compare media direction */
3221 if (call_med->dir != new_si->dir)
3222 return PJ_TRUE;
3223
3224 /* Get current active stream info */
3225 if (call_med->strm.a.stream) {
3226 pjmedia_stream_get_info(call_med->strm.a.stream, &the_old_si);
3227 old_si = &the_old_si;
3228 old_ci = &old_si->fmt;
3229 old_cp = old_si->param;
3230 } else {
3231 /* The stream is inactive. */
3232 return (new_si->dir != PJMEDIA_DIR_NONE);
3233 }
3234
3235 /* Compare remote RTP address. If ICE is running, change in default
3236 * address can happen after negotiation, this can be handled
3237 * internally by ICE and does not need to cause media restart.
3238 */
3239 if (old_si->rtcp_mux != new_si->rtcp_mux)
3240 return PJ_TRUE;
3241 if (!is_ice_running(call_med->tp) &&
3242 pj_sockaddr_cmp(&old_si->rem_addr, &new_si->rem_addr))
3243 {
3244 return PJ_TRUE;
3245 }
3246
3247 /* Compare codec info */
3248 if (pj_stricmp(&old_ci->encoding_name, &new_ci->encoding_name) ||
3249 old_ci->clock_rate != new_ci->clock_rate ||
3250 old_ci->channel_cnt != new_ci->channel_cnt ||
3251 old_si->rx_pt != new_si->rx_pt ||
3252 old_si->tx_pt != new_si->tx_pt ||
3253 old_si->rx_event_pt != new_si->tx_event_pt ||
3254 old_si->tx_event_pt != new_si->tx_event_pt)
3255 {
3256 return PJ_TRUE;
3257 }
3258
3259 /* Compare codec param */
3260 if (old_cp->setting.frm_per_pkt != new_cp->setting.frm_per_pkt ||
3261 old_cp->setting.vad != new_cp->setting.vad ||
3262 old_cp->setting.cng != new_cp->setting.cng ||
3263 old_cp->setting.plc != new_cp->setting.plc ||
3264 old_cp->setting.penh != new_cp->setting.penh ||
3265 !match_codec_fmtp(&old_cp->setting.dec_fmtp,
3266 &new_cp->setting.dec_fmtp) ||
3267 !match_codec_fmtp(&old_cp->setting.enc_fmtp,
3268 &new_cp->setting.enc_fmtp))
3269 {
3270 return PJ_TRUE;
3271 }
3272 }
3273
3274 #if PJMEDIA_HAS_VIDEO
3275 else if (call_med->type == PJMEDIA_TYPE_VIDEO) {
3276 pjmedia_vid_stream_info the_old_si;
3277 const pjmedia_vid_stream_info *old_si = NULL;
3278 const pjmedia_vid_stream_info *new_si = &new_si_->info.vid;
3279 const pjmedia_vid_codec_info *old_ci = NULL;
3280 const pjmedia_vid_codec_info *new_ci = &new_si->codec_info;
3281 const pjmedia_vid_codec_param *old_cp = NULL;
3282 const pjmedia_vid_codec_param *new_cp = new_si->codec_param;
3283
3284 /* Compare media direction */
3285 if (call_med->dir != new_si->dir)
3286 return PJ_TRUE;
3287
3288 /* Get current active stream info */
3289 if (call_med->strm.v.stream) {
3290 pjmedia_vid_stream_get_info(call_med->strm.v.stream, &the_old_si);
3291 old_si = &the_old_si;
3292 old_ci = &old_si->codec_info;
3293 old_cp = old_si->codec_param;
3294 } else {
3295 /* The stream is inactive. */
3296 return (new_si->dir != PJMEDIA_DIR_NONE);
3297 }
3298
3299 /* Compare remote RTP address. If ICE is running, change in default
3300 * address can happen after negotiation, this can be handled
3301 * internally by ICE and does not need to cause media restart.
3302 */
3303 if (old_si->rtcp_mux != new_si->rtcp_mux)
3304 return PJ_TRUE;
3305 if (!is_ice_running(call_med->tp) &&
3306 pj_sockaddr_cmp(&old_si->rem_addr, &new_si->rem_addr))
3307 {
3308 return PJ_TRUE;
3309 }
3310
3311 /* Compare codec info */
3312 if (pj_stricmp(&old_ci->encoding_name, &new_ci->encoding_name) ||
3313 old_si->rx_pt != new_si->rx_pt ||
3314 old_si->tx_pt != new_si->tx_pt)
3315 {
3316 return PJ_TRUE;
3317 }
3318
3319 /* Compare codec param */
3320 if (/* old_cp->enc_mtu != new_cp->enc_mtu || */
3321 pj_memcmp(&old_cp->enc_fmt.det, &new_cp->enc_fmt.det,
3322 sizeof(pjmedia_video_format_detail)) ||
3323 !match_codec_fmtp(&old_cp->dec_fmtp, &new_cp->dec_fmtp) ||
3324 !match_codec_fmtp(&old_cp->enc_fmtp, &new_cp->enc_fmtp))
3325 {
3326 return PJ_TRUE;
3327 }
3328 }
3329
3330 #endif
3331
3332 else {
3333 /* Just return PJ_TRUE for other media type */
3334 return PJ_TRUE;
3335 }
3336
3337 return PJ_FALSE;
3338 }
3339
3340 #else /* PJSUA_MEDIA_HAS_PJMEDIA || PJSUA_THIRD_PARTY_STREAM_HAS_GET_INFO */
3341
is_media_changed(const pjsua_call * call,unsigned med_idx,const pjsua_stream_info * new_si_)3342 static pj_bool_t is_media_changed(const pjsua_call *call,
3343 unsigned med_idx,
3344 const pjsua_stream_info *new_si_)
3345 {
3346 PJ_UNUSED_ARG(call);
3347 PJ_UNUSED_ARG(med_idx);
3348 PJ_UNUSED_ARG(new_si_);
3349 /* Always assume that media has been changed */
3350 return PJ_TRUE;
3351 }
3352
3353 #endif /* PJSUA_MEDIA_HAS_PJMEDIA || PJSUA_THIRD_PARTY_STREAM_HAS_GET_INFO */
3354
3355
pjsua_media_channel_update(pjsua_call_id call_id,const pjmedia_sdp_session * local_sdp,const pjmedia_sdp_session * remote_sdp)3356 pj_status_t pjsua_media_channel_update(pjsua_call_id call_id,
3357 const pjmedia_sdp_session *local_sdp,
3358 const pjmedia_sdp_session *remote_sdp)
3359 {
3360 pjsua_call *call = &pjsua_var.calls[call_id];
3361 pjsua_acc *acc = &pjsua_var.acc[call->acc_id];
3362 pj_pool_t *tmp_pool = call->inv->pool_prov;
3363 unsigned mi;
3364 pj_bool_t got_media = PJ_FALSE;
3365 pj_status_t status = PJ_SUCCESS;
3366
3367 const pj_str_t STR_AUDIO = { "audio", 5 };
3368 const pj_str_t STR_VIDEO = { "video", 5 };
3369 pj_uint8_t maudidx[PJSUA_MAX_CALL_MEDIA];
3370 unsigned maudcnt = PJ_ARRAY_SIZE(maudidx);
3371 unsigned mtotaudcnt = PJ_ARRAY_SIZE(maudidx);
3372 pj_uint8_t mvididx[PJSUA_MAX_CALL_MEDIA];
3373 unsigned mvidcnt = PJ_ARRAY_SIZE(mvididx);
3374 unsigned mtotvidcnt = PJ_ARRAY_SIZE(mvididx);
3375 pj_bool_t need_renego_sdp = PJ_FALSE;
3376
3377 if (pjsua_get_state() != PJSUA_STATE_RUNNING)
3378 return PJ_EBUSY;
3379
3380 PJ_LOG(4,(THIS_FILE, "Call %d: updating media..", call_id));
3381 pj_log_push_indent();
3382
3383 /* Destroy existing media session, if any. */
3384 //stop_media_session(call->index);
3385
3386 /* Call media count must be at least equal to SDP media. Note that
3387 * it may not be equal when remote removed any SDP media line.
3388 */
3389 pj_assert(call->med_prov_cnt >= local_sdp->media_count);
3390
3391 /* Reset audio_idx first */
3392 call->audio_idx = -1;
3393
3394 /* Sort audio/video based on "quality" */
3395 sort_media(local_sdp, &STR_AUDIO, acc->cfg.use_srtp,
3396 maudidx, &maudcnt, &mtotaudcnt);
3397 #if PJMEDIA_HAS_VIDEO
3398 sort_media(local_sdp, &STR_VIDEO, acc->cfg.use_srtp,
3399 mvididx, &mvidcnt, &mtotvidcnt);
3400 #else
3401 PJ_UNUSED_ARG(STR_VIDEO);
3402 mvidcnt = mtotvidcnt = 0;
3403 #endif
3404
3405 /* We need to re-nego SDP or modify our answer when:
3406 * - media count exceeds the configured limit,
3407 * - RTCP-FB is enabled (so a=rtcp-fb will only be printed for negotiated
3408 * codecs)
3409 */
3410 if (!pjmedia_sdp_neg_was_answer_remote(call->inv->neg) &&
3411 ((maudcnt > call->opt.aud_cnt || mvidcnt > call->opt.vid_cnt) ||
3412 (acc->cfg.rtcp_fb_cfg.cap_count)))
3413 {
3414 pjmedia_sdp_session *local_sdp_renego = NULL;
3415
3416 local_sdp_renego = pjmedia_sdp_session_clone(tmp_pool, local_sdp);
3417 local_sdp = local_sdp_renego;
3418 need_renego_sdp = PJ_TRUE;
3419
3420 /* Add RTCP-FB info into local SDP answer */
3421 if (acc->cfg.rtcp_fb_cfg.cap_count) {
3422 for (mi=0; mi < local_sdp_renego->media_count; ++mi) {
3423 status = pjmedia_rtcp_fb_encode_sdp(
3424 tmp_pool, pjsua_var.med_endpt,
3425 &acc->cfg.rtcp_fb_cfg,
3426 local_sdp_renego, mi, remote_sdp);
3427 if (status != PJ_SUCCESS) {
3428 PJ_PERROR(3,(THIS_FILE, status,
3429 "Call %d media %d: Failed to encode RTCP-FB "
3430 "setting to SDP",
3431 call_id, mi));
3432 }
3433 }
3434 }
3435
3436 /* Applying media count limitation. Note that in generating SDP
3437 * answer, no media count limitation applied as we didn't know yet
3438 * which media would pass the SDP negotiation.
3439 */
3440 if (maudcnt > call->opt.aud_cnt || mvidcnt > call->opt.vid_cnt)
3441 {
3442 maudcnt = PJ_MIN(maudcnt, call->opt.aud_cnt);
3443 mvidcnt = PJ_MIN(mvidcnt, call->opt.vid_cnt);
3444
3445 for (mi=0; mi < local_sdp_renego->media_count; ++mi) {
3446 pjmedia_sdp_media *m = local_sdp_renego->media[mi];
3447
3448 if (m->desc.port == 0 ||
3449 pj_memchr(maudidx, mi, maudcnt*sizeof(maudidx[0])) ||
3450 pj_memchr(mvididx, mi, mvidcnt*sizeof(mvididx[0])))
3451 {
3452 continue;
3453 }
3454
3455 /* Deactivate this excess media */
3456 pjmedia_sdp_media_deactivate(tmp_pool, m);
3457 }
3458 }
3459 }
3460
3461 /* Update call media from provisional media */
3462 call->med_cnt = call->med_prov_cnt;
3463 pj_memcpy(call->media, call->media_prov,
3464 sizeof(call->media_prov[0]) * call->med_prov_cnt);
3465
3466 /* Process each media stream */
3467 for (mi=0; mi < call->med_cnt; ++mi) {
3468 pjsua_call_media *call_med = &call->media[mi];
3469 pj_bool_t media_changed = PJ_FALSE;
3470
3471 if (mi >= local_sdp->media_count ||
3472 mi >= remote_sdp->media_count)
3473 {
3474 /* This may happen when remote removed any SDP media lines in
3475 * its re-offer.
3476 */
3477
3478 /* Stop stream */
3479 stop_media_stream(call, mi);
3480
3481 /* Close the media transport */
3482 if (call_med->tp) {
3483 pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_NULL);
3484 pjmedia_transport_close(call_med->tp);
3485 call_med->tp = call_med->tp_orig = NULL;
3486 }
3487 continue;
3488 #if 0
3489 /* Something is wrong */
3490 PJ_LOG(1,(THIS_FILE, "Error updating media for call %d: "
3491 "invalid media index %d in SDP", call_id, mi));
3492 status = PJMEDIA_SDP_EINSDP;
3493 goto on_error;
3494 #endif
3495 }
3496
3497 /* Apply media update action */
3498 if (call_med->type==PJMEDIA_TYPE_AUDIO) {
3499 pjmedia_stream_info the_si, *si = &the_si;
3500 pjsua_stream_info stream_info;
3501
3502 status = pjmedia_stream_info_from_sdp(
3503 si, tmp_pool, pjsua_var.med_endpt,
3504 local_sdp, remote_sdp, mi);
3505 if (status != PJ_SUCCESS) {
3506 PJ_PERROR(1,(THIS_FILE, status,
3507 "pjmedia_stream_info_from_sdp() failed "
3508 "for call_id %d media %d",
3509 call_id, mi));
3510 goto on_check_med_status;
3511 }
3512
3513 /* Check if remote wants RTP and RTCP multiplexing,
3514 * but we don't enable it.
3515 */
3516 if (si->rtcp_mux && !call_med->enable_rtcp_mux) {
3517 si->rtcp_mux = PJ_FALSE;
3518 }
3519
3520 /* Codec parameter of stream info (si->param) can be NULL if
3521 * the stream is rejected or disabled.
3522 */
3523 /* Override ptime, if this option is specified. */
3524 if (pjsua_var.media_cfg.ptime != 0 && si->param) {
3525 si->param->setting.frm_per_pkt = (pj_uint8_t)
3526 (pjsua_var.media_cfg.ptime / si->param->info.frm_ptime);
3527 if (si->param->setting.frm_per_pkt == 0)
3528 si->param->setting.frm_per_pkt = 1;
3529 }
3530
3531 /* Disable VAD, if this option is specified. */
3532 if (pjsua_var.media_cfg.no_vad && si->param) {
3533 si->param->setting.vad = 0;
3534 }
3535
3536 /* Check if this media is changed */
3537 stream_info.type = PJMEDIA_TYPE_AUDIO;
3538 stream_info.info.aud = the_si;
3539 if (pjsua_var.media_cfg.no_smart_media_update ||
3540 is_media_changed(call, mi, &stream_info))
3541 {
3542 media_changed = PJ_TRUE;
3543 /* Stop the media */
3544 stop_media_stream(call, mi);
3545 } else {
3546 PJ_LOG(4,(THIS_FILE, "Call %d: stream #%d (audio) unchanged.",
3547 call_id, mi));
3548 }
3549
3550 /* Check if no media is active */
3551 if (local_sdp->media[mi]->desc.port == 0) {
3552
3553 /* Update call media state and direction */
3554 call_med->state = PJSUA_CALL_MEDIA_NONE;
3555 call_med->dir = PJMEDIA_DIR_NONE;
3556
3557 } else if (call_med->tp) {
3558 pjmedia_transport_info tp_info;
3559 pjmedia_srtp_info *srtp_info;
3560
3561 /* Call media direction */
3562 call_med->dir = si->dir;
3563
3564 /* Call media state */
3565 if (call->local_hold)
3566 call_med->state = PJSUA_CALL_MEDIA_LOCAL_HOLD;
3567 else if (call_med->dir == PJMEDIA_DIR_DECODING)
3568 call_med->state = PJSUA_CALL_MEDIA_REMOTE_HOLD;
3569 else
3570 call_med->state = PJSUA_CALL_MEDIA_ACTIVE;
3571
3572 if (call->inv->following_fork) {
3573 unsigned options = (call_med->enable_rtcp_mux?
3574 PJMEDIA_TPMED_RTCP_MUX: 0);
3575 /* Normally media transport will automatically restart
3576 * itself (if needed, based on info from the SDP) in
3577 * pjmedia_transport_media_start(), however in "following
3578 * forked media" case (see #1644), we need to explicitly
3579 * restart it as it cannot detect fork scenario from
3580 * the SDP only.
3581 */
3582 status = pjmedia_transport_media_stop(call_med->tp);
3583 if (status != PJ_SUCCESS) {
3584 PJ_PERROR(1,(THIS_FILE, status,
3585 "pjmedia_transport_media_stop() failed "
3586 "for call_id %d media %d",
3587 call_id, mi));
3588 goto on_check_med_status;
3589 }
3590 status = pjmedia_transport_media_create(call_med->tp,
3591 tmp_pool,
3592 options, NULL, mi);
3593 if (status != PJ_SUCCESS) {
3594 PJ_PERROR(1,(THIS_FILE, status,
3595 "pjmedia_transport_media_create() failed "
3596 "for call_id %d media %d",
3597 call_id, mi));
3598 goto on_check_med_status;
3599 }
3600 }
3601
3602 /* Start/restart media transport based on info in SDP */
3603 status = pjmedia_transport_media_start(call_med->tp,
3604 tmp_pool, local_sdp,
3605 remote_sdp, mi);
3606 if (status != PJ_SUCCESS) {
3607 PJ_PERROR(1,(THIS_FILE, status,
3608 "pjmedia_transport_media_start() failed "
3609 "for call_id %d media %d",
3610 call_id, mi));
3611 goto on_check_med_status;
3612 }
3613
3614 pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_RUNNING);
3615
3616 /* Get remote SRTP usage policy */
3617 pjmedia_transport_info_init(&tp_info);
3618 pjmedia_transport_get_info(call_med->tp, &tp_info);
3619 srtp_info = (pjmedia_srtp_info*)
3620 pjmedia_transport_info_get_spc_info(
3621 &tp_info, PJMEDIA_TRANSPORT_TYPE_SRTP);
3622 if (srtp_info) {
3623 call_med->rem_srtp_use = srtp_info->peer_use;
3624 }
3625
3626 /* Update audio channel */
3627 if (media_changed) {
3628 status = pjsua_aud_channel_update(call_med,
3629 call->inv->pool, si,
3630 local_sdp, remote_sdp);
3631 if (status != PJ_SUCCESS) {
3632 PJ_PERROR(1,(THIS_FILE, status,
3633 "pjsua_aud_channel_update() failed "
3634 "for call_id %d media %d",
3635 call_id, mi));
3636 goto on_check_med_status;
3637 }
3638
3639 if (pjmedia_transport_info_get_spc_info(
3640 &tp_info, PJMEDIA_TRANSPORT_TYPE_LOOP))
3641 {
3642 pjmedia_transport_loop_disable_rx(
3643 call_med->tp, call_med->strm.a.stream,
3644 !acc->cfg.enable_loopback);
3645 }
3646 }
3647 }
3648
3649 /* Print info. */
3650 if (status == PJ_SUCCESS) {
3651 char info[80];
3652 int info_len = 0;
3653 int len;
3654 const char *dir;
3655
3656 switch (si->dir) {
3657 case PJMEDIA_DIR_NONE:
3658 dir = "inactive";
3659 break;
3660 case PJMEDIA_DIR_ENCODING:
3661 dir = "sendonly";
3662 break;
3663 case PJMEDIA_DIR_DECODING:
3664 dir = "recvonly";
3665 break;
3666 case PJMEDIA_DIR_ENCODING_DECODING:
3667 dir = "sendrecv";
3668 break;
3669 default:
3670 dir = "unknown";
3671 break;
3672 }
3673 len = pj_ansi_sprintf( info+info_len,
3674 ", stream #%d: %.*s (%s)", mi,
3675 (int)si->fmt.encoding_name.slen,
3676 si->fmt.encoding_name.ptr,
3677 dir);
3678 if (len > 0)
3679 info_len += len;
3680 PJ_LOG(4,(THIS_FILE,"Audio updated%s", info));
3681 }
3682
3683
3684 if (call->audio_idx==-1 && status==PJ_SUCCESS &&
3685 si->dir != PJMEDIA_DIR_NONE)
3686 {
3687 call->audio_idx = mi;
3688 }
3689
3690 #if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
3691 } else if (call_med->type==PJMEDIA_TYPE_VIDEO) {
3692 pjmedia_vid_stream_info the_si, *si = &the_si;
3693 pjsua_stream_info stream_info;
3694
3695 status = pjmedia_vid_stream_info_from_sdp(
3696 si, tmp_pool, pjsua_var.med_endpt,
3697 local_sdp, remote_sdp, mi);
3698 if (status != PJ_SUCCESS) {
3699 PJ_PERROR(1,(THIS_FILE, status,
3700 "pjmedia_vid_stream_info_from_sdp() failed "
3701 "for call_id %d media %d",
3702 call_id, mi));
3703 goto on_check_med_status;
3704 }
3705
3706 /* Check if remote wants RTP and RTCP multiplexing,
3707 * but we don't enable it.
3708 */
3709 if (si->rtcp_mux && !call_med->enable_rtcp_mux) {
3710 si->rtcp_mux = PJ_FALSE;
3711 }
3712
3713 /* Check if this media is changed */
3714 stream_info.type = PJMEDIA_TYPE_VIDEO;
3715 stream_info.info.vid = the_si;
3716 if (is_media_changed(call, mi, &stream_info)) {
3717 media_changed = PJ_TRUE;
3718 /* Stop the media */
3719 stop_media_stream(call, mi);
3720 } else {
3721 PJ_LOG(4,(THIS_FILE, "Call %d: stream #%d (video) unchanged.",
3722 call_id, mi));
3723 }
3724
3725 /* Check if no media is active */
3726 if (si->dir == PJMEDIA_DIR_NONE) {
3727
3728 /* Update call media state and direction */
3729 call_med->state = PJSUA_CALL_MEDIA_NONE;
3730 call_med->dir = PJMEDIA_DIR_NONE;
3731
3732 } else if (call_med->tp) {
3733 pjmedia_transport_info tp_info;
3734 pjmedia_srtp_info *srtp_info;
3735
3736 /* Call media direction */
3737 call_med->dir = si->dir;
3738
3739 /* Call media state */
3740 if (call->local_hold)
3741 call_med->state = PJSUA_CALL_MEDIA_LOCAL_HOLD;
3742 else if (call_med->dir == PJMEDIA_DIR_DECODING)
3743 call_med->state = PJSUA_CALL_MEDIA_REMOTE_HOLD;
3744 else
3745 call_med->state = PJSUA_CALL_MEDIA_ACTIVE;
3746
3747 /* Start/restart media transport */
3748 status = pjmedia_transport_media_start(call_med->tp,
3749 tmp_pool, local_sdp,
3750 remote_sdp, mi);
3751 if (status != PJ_SUCCESS) {
3752 PJ_PERROR(1,(THIS_FILE, status,
3753 "pjmedia_transport_media_start() failed "
3754 "for call_id %d media %d",
3755 call_id, mi));
3756 goto on_check_med_status;
3757 }
3758
3759 pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_RUNNING);
3760
3761 /* Get remote SRTP usage policy */
3762 pjmedia_transport_info_init(&tp_info);
3763 pjmedia_transport_get_info(call_med->tp, &tp_info);
3764 srtp_info = (pjmedia_srtp_info*)
3765 pjmedia_transport_info_get_spc_info(
3766 &tp_info, PJMEDIA_TRANSPORT_TYPE_SRTP);
3767 if (srtp_info) {
3768 call_med->rem_srtp_use = srtp_info->peer_use;
3769 }
3770
3771 /* Update audio channel */
3772 if (media_changed) {
3773 status = pjsua_vid_channel_update(call_med,
3774 call->inv->pool, si,
3775 local_sdp, remote_sdp);
3776 if (status != PJ_SUCCESS) {
3777 PJ_PERROR(1,(THIS_FILE, status,
3778 "pjsua_vid_channel_update() failed "
3779 "for call_id %d media %d",
3780 call_id, mi));
3781 goto on_check_med_status;
3782 }
3783 }
3784 }
3785
3786 /* Print info. */
3787 {
3788 char info[80];
3789 int info_len = 0;
3790 int len;
3791 const char *dir;
3792
3793 switch (si->dir) {
3794 case PJMEDIA_DIR_NONE:
3795 dir = "inactive";
3796 break;
3797 case PJMEDIA_DIR_ENCODING:
3798 dir = "sendonly";
3799 break;
3800 case PJMEDIA_DIR_DECODING:
3801 dir = "recvonly";
3802 break;
3803 case PJMEDIA_DIR_ENCODING_DECODING:
3804 dir = "sendrecv";
3805 break;
3806 default:
3807 dir = "unknown";
3808 break;
3809 }
3810 len = pj_ansi_sprintf( info+info_len,
3811 ", stream #%d: %.*s (%s)", mi,
3812 (int)si->codec_info.encoding_name.slen,
3813 si->codec_info.encoding_name.ptr,
3814 dir);
3815 if (len > 0)
3816 info_len += len;
3817 PJ_LOG(4,(THIS_FILE,"Video updated%s", info));
3818 }
3819
3820 #endif
3821 } else {
3822 status = PJMEDIA_EUNSUPMEDIATYPE;
3823 }
3824
3825 /* Close the transport of deactivated media, need this here as media
3826 * can be deactivated by the SDP negotiation and the max media count
3827 * (account) setting.
3828 */
3829 if (local_sdp->media[mi]->desc.port==0 && call_med->tp) {
3830 pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_NULL);
3831 pjmedia_transport_close(call_med->tp);
3832 call_med->tp = call_med->tp_orig = NULL;
3833 }
3834
3835 on_check_med_status:
3836 if (status != PJ_SUCCESS) {
3837 /* Stop stream */
3838 stop_media_stream(call, mi);
3839
3840 /* Close the media transport */
3841 if (call_med->tp) {
3842 pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_NULL);
3843 pjmedia_transport_close(call_med->tp);
3844 call_med->tp = call_med->tp_orig = NULL;
3845 }
3846
3847 /* Update media states */
3848 call_med->state = PJSUA_CALL_MEDIA_ERROR;
3849 call_med->dir = PJMEDIA_DIR_NONE;
3850
3851 if (status != PJMEDIA_EUNSUPMEDIATYPE) {
3852 PJ_PERROR(1, (THIS_FILE, status, "Error updating media "
3853 "call%02d:%d", call_id, mi));
3854 } else {
3855 PJ_PERROR(3, (THIS_FILE, status, "Skipped updating media "
3856 "call%02d:%d (media type=%s)", call_id, mi,
3857 pjmedia_type_name(call_med->type)));
3858 }
3859
3860 } else {
3861 /* Only set 'got_media' flag if this media is not disabled */
3862 if (local_sdp->media[mi]->desc.port != 0)
3863 got_media = PJ_TRUE;
3864 }
3865 }
3866
3867 /* Sync provisional media to call media */
3868 call->med_prov_cnt = call->med_cnt;
3869 pj_memcpy(call->media_prov, call->media,
3870 sizeof(call->media[0]) * call->med_cnt);
3871
3872 /* Perform SDP re-negotiation. */
3873 if (got_media && need_renego_sdp) {
3874 pjmedia_sdp_neg *neg = call->inv->neg;
3875
3876 status = pjmedia_sdp_neg_set_remote_offer(tmp_pool, neg, remote_sdp);
3877 if (status != PJ_SUCCESS)
3878 goto on_error;
3879
3880 status = pjmedia_sdp_neg_set_local_answer(tmp_pool, neg, local_sdp);
3881 if (status != PJ_SUCCESS)
3882 goto on_error;
3883
3884 status = pjmedia_sdp_neg_negotiate(tmp_pool, neg, 0);
3885 if (status != PJ_SUCCESS)
3886 goto on_error;
3887 }
3888
3889 pj_log_pop_indent();
3890 return (got_media? PJ_SUCCESS : PJMEDIA_SDPNEG_ENOMEDIA);
3891
3892 on_error:
3893 pj_log_pop_indent();
3894 return status;
3895 }
3896
3897 /*****************************************************************************
3898 * Codecs.
3899 */
3900
3901 /*
3902 * Enum all supported codecs in the system.
3903 */
pjsua_enum_codecs(pjsua_codec_info id[],unsigned * p_count)3904 PJ_DEF(pj_status_t) pjsua_enum_codecs( pjsua_codec_info id[],
3905 unsigned *p_count )
3906 {
3907 pjmedia_codec_mgr *codec_mgr;
3908 pjmedia_codec_info info[32];
3909 unsigned i, count, prio[32];
3910 pj_status_t status;
3911
3912 codec_mgr = pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt);
3913 count = PJ_ARRAY_SIZE(info);
3914 status = pjmedia_codec_mgr_enum_codecs( codec_mgr, &count, info, prio);
3915 if (status != PJ_SUCCESS) {
3916 *p_count = 0;
3917 return status;
3918 }
3919
3920 if (count > *p_count) count = *p_count;
3921
3922 for (i=0; i<count; ++i) {
3923 pj_bzero(&id[i], sizeof(pjsua_codec_info));
3924
3925 pjmedia_codec_info_to_id(&info[i], id[i].buf_, sizeof(id[i].buf_));
3926 id[i].codec_id = pj_str(id[i].buf_);
3927 id[i].priority = (pj_uint8_t) prio[i];
3928 }
3929
3930 *p_count = count;
3931
3932 return PJ_SUCCESS;
3933 }
3934
3935
3936 /*
3937 * Change codec priority.
3938 */
pjsua_codec_set_priority(const pj_str_t * codec_id,pj_uint8_t priority)3939 PJ_DEF(pj_status_t) pjsua_codec_set_priority( const pj_str_t *codec_id,
3940 pj_uint8_t priority )
3941 {
3942 const pj_str_t all = { NULL, 0 };
3943 pjmedia_codec_mgr *codec_mgr;
3944
3945 codec_mgr = pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt);
3946
3947 if (codec_id->slen==1 && *codec_id->ptr=='*')
3948 codec_id = &all;
3949
3950 return pjmedia_codec_mgr_set_codec_priority(codec_mgr, codec_id,
3951 priority);
3952 }
3953
3954
3955 /*
3956 * Get codec parameters.
3957 */
pjsua_codec_get_param(const pj_str_t * codec_id,pjmedia_codec_param * param)3958 PJ_DEF(pj_status_t) pjsua_codec_get_param( const pj_str_t *codec_id,
3959 pjmedia_codec_param *param )
3960 {
3961 const pj_str_t all = { NULL, 0 };
3962 const pjmedia_codec_info *info;
3963 pjmedia_codec_mgr *codec_mgr;
3964 unsigned count = 1;
3965 pj_status_t status;
3966
3967 codec_mgr = pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt);
3968
3969 if (codec_id->slen==1 && *codec_id->ptr=='*')
3970 codec_id = &all;
3971
3972 status = pjmedia_codec_mgr_find_codecs_by_id(codec_mgr, codec_id,
3973 &count, &info, NULL);
3974 if (status != PJ_SUCCESS)
3975 return status;
3976
3977 if (count != 1)
3978 return (count > 1? PJ_ETOOMANY : PJ_ENOTFOUND);
3979
3980 status = pjmedia_codec_mgr_get_default_param( codec_mgr, info, param);
3981 return status;
3982 }
3983
3984
3985 /*
3986 * Set codec parameters.
3987 */
pjsua_codec_set_param(const pj_str_t * codec_id,const pjmedia_codec_param * param)3988 PJ_DEF(pj_status_t) pjsua_codec_set_param( const pj_str_t *codec_id,
3989 const pjmedia_codec_param *param)
3990 {
3991 const pjmedia_codec_info *info[2];
3992 pjmedia_codec_mgr *codec_mgr;
3993 unsigned count = 2;
3994 pj_status_t status;
3995
3996 codec_mgr = pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt);
3997
3998 status = pjmedia_codec_mgr_find_codecs_by_id(codec_mgr, codec_id,
3999 &count, info, NULL);
4000 if (status != PJ_SUCCESS)
4001 return status;
4002
4003 /* Codec ID should be specific, except for G.722.1 */
4004 if (count > 1 &&
4005 pj_strnicmp2(codec_id, "G7221/16", 8) != 0 &&
4006 pj_strnicmp2(codec_id, "G7221/32", 8) != 0)
4007 {
4008 pj_assert(!"Codec ID is not specific");
4009 return PJ_ETOOMANY;
4010 }
4011
4012 status = pjmedia_codec_mgr_set_default_param(codec_mgr, info[0], param);
4013 return status;
4014 }
4015
4016
pjsua_media_apply_xml_control(pjsua_call_id call_id,const pj_str_t * xml_st)4017 pj_status_t pjsua_media_apply_xml_control(pjsua_call_id call_id,
4018 const pj_str_t *xml_st)
4019 {
4020 #if PJMEDIA_HAS_VIDEO
4021 pjsua_call *call = &pjsua_var.calls[call_id];
4022 const pj_str_t PICT_FAST_UPDATE = {"picture_fast_update", 19};
4023
4024 if (pj_strstr(xml_st, &PICT_FAST_UPDATE)) {
4025 unsigned i;
4026
4027 PJ_LOG(4,(THIS_FILE, "Received keyframe request via SIP INFO"));
4028
4029 for (i = 0; i < call->med_cnt; ++i) {
4030 pjsua_call_media *cm = &call->media[i];
4031 if (cm->type != PJMEDIA_TYPE_VIDEO || !cm->strm.v.stream)
4032 continue;
4033
4034 pjmedia_vid_stream_send_keyframe(cm->strm.v.stream);
4035 }
4036
4037 return PJ_SUCCESS;
4038 }
4039 #endif
4040
4041 /* Just to avoid compiler warning of unused var */
4042 PJ_UNUSED_ARG(call_id);
4043 PJ_UNUSED_ARG(xml_st);
4044
4045 return PJ_ENOTSUP;
4046 }
4047
4048