~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.2.1/pjsip/src/pjsua-lib/pjsua_media.c

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2015-01-07 14:51:16 UTC
  • mfrom: (4.3.5 sid)
  • Revision ID: package-import@ubuntu.com-20150107145116-yxnafinf4lrdvrmx
Tags: 1.4.1-0.1ubuntu1
* Merge with Debian, remaining changes:
 - Drop soprano, nepomuk build-dep
* Drop ubuntu patches, now upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: pjsua_media.c 4750 2014-02-19 04:11:43Z bennylp $ */
 
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
#define DEFAULT_RTP_PORT        4000
 
27
 
 
28
#ifndef PJSUA_REQUIRE_CONSECUTIVE_RTCP_PORT
 
29
#   define PJSUA_REQUIRE_CONSECUTIVE_RTCP_PORT  0
 
30
#endif
 
31
 
 
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
}
 
40
 
 
41
 
 
42
/**
 
43
 * Init media subsystems.
 
44
 */
 
45
pj_status_t pjsua_media_subsys_init(const pjsua_media_config *cfg)
 
46
{
 
47
    pj_status_t status;
 
48
 
 
49
    pj_log_push_indent();
 
50
 
 
51
    /* Specify which audio device settings are save-able */
 
52
    pjsua_var.aud_svmask = 0xFFFFFFFF;
 
53
    /* These are not-settable */
 
54
    pjsua_var.aud_svmask &= ~(PJMEDIA_AUD_DEV_CAP_EXT_FORMAT |
 
55
                              PJMEDIA_AUD_DEV_CAP_INPUT_SIGNAL_METER |
 
56
                              PJMEDIA_AUD_DEV_CAP_OUTPUT_SIGNAL_METER);
 
57
    /* EC settings use different API */
 
58
    pjsua_var.aud_svmask &= ~(PJMEDIA_AUD_DEV_CAP_EC |
 
59
                              PJMEDIA_AUD_DEV_CAP_EC_TAIL);
 
60
 
 
61
    /* Copy configuration */
 
62
    pjsua_media_config_dup(pjsua_var.pool, &pjsua_var.media_cfg, cfg);
 
63
 
 
64
    /* Normalize configuration */
 
65
    if (pjsua_var.media_cfg.snd_clock_rate == 0) {
 
66
        pjsua_var.media_cfg.snd_clock_rate = pjsua_var.media_cfg.clock_rate;
 
67
    }
 
68
 
 
69
    if (pjsua_var.media_cfg.has_ioqueue &&
 
70
        pjsua_var.media_cfg.thread_cnt == 0)
 
71
    {
 
72
        pjsua_var.media_cfg.thread_cnt = 1;
 
73
    }
 
74
 
 
75
    if (pjsua_var.media_cfg.max_media_ports < pjsua_var.ua_cfg.max_calls) {
 
76
        pjsua_var.media_cfg.max_media_ports = pjsua_var.ua_cfg.max_calls + 2;
 
77
    }
 
78
 
 
79
    /* Create media endpoint. */
 
80
    status = pjmedia_endpt_create(&pjsua_var.cp.factory, 
 
81
                                  pjsua_var.media_cfg.has_ioqueue? NULL :
 
82
                                     pjsip_endpt_get_ioqueue(pjsua_var.endpt),
 
83
                                  pjsua_var.media_cfg.thread_cnt,
 
84
                                  &pjsua_var.med_endpt);
 
85
    if (status != PJ_SUCCESS) {
 
86
        pjsua_perror(THIS_FILE, 
 
87
                     "Media stack initialization has returned error", 
 
88
                     status);
 
89
        goto on_error;
 
90
    }
 
91
 
 
92
    status = pjsua_aud_subsys_init();
 
93
    if (status != PJ_SUCCESS)
 
94
        goto on_error;
 
95
 
 
96
#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
 
97
    /* Initialize SRTP library (ticket #788). */
 
98
    status = pjmedia_srtp_init_lib(pjsua_var.med_endpt);
 
99
    if (status != PJ_SUCCESS) {
 
100
        pjsua_perror(THIS_FILE, "Error initializing SRTP library", 
 
101
                     status);
 
102
        goto on_error;
 
103
    }
 
104
#endif
 
105
 
 
106
    /* Video */
 
107
#if PJMEDIA_HAS_VIDEO
 
108
    status = pjsua_vid_subsys_init();
 
109
    if (status != PJ_SUCCESS)
 
110
        goto on_error;
 
111
#endif
 
112
 
 
113
    pj_log_pop_indent();
 
114
    return PJ_SUCCESS;
 
115
 
 
116
on_error:
 
117
    pj_log_pop_indent();
 
118
    return status;
 
119
}
 
120
 
 
121
/*
 
122
 * Start pjsua media subsystem.
 
123
 */
 
124
pj_status_t pjsua_media_subsys_start(void)
 
125
{
 
126
    pj_status_t status;
 
127
 
 
128
    pj_log_push_indent();
 
129
 
 
130
#if DISABLED_FOR_TICKET_1185
 
131
    /* Create media for calls, if none is specified */
 
132
    if (pjsua_var.calls[0].media[0].tp == NULL) {
 
133
        pjsua_transport_config transport_cfg;
 
134
 
 
135
        /* Create default transport config */
 
136
        pjsua_transport_config_default(&transport_cfg);
 
137
        transport_cfg.port = DEFAULT_RTP_PORT;
 
138
 
 
139
        status = pjsua_media_transports_create(&transport_cfg);
 
140
        if (status != PJ_SUCCESS) {
 
141
            pj_log_pop_indent();
 
142
            return status;
 
143
        }
 
144
    }
 
145
#endif
 
146
 
 
147
    /* Audio */
 
148
    status = pjsua_aud_subsys_start();
 
149
    if (status != PJ_SUCCESS) {
 
150
        pj_log_pop_indent();
 
151
        return status;
 
152
    }
 
153
 
 
154
    /* Video */
 
155
#if PJMEDIA_HAS_VIDEO
 
156
    status = pjsua_vid_subsys_start();
 
157
    if (status != PJ_SUCCESS) {
 
158
        pjsua_aud_subsys_destroy();
 
159
        pj_log_pop_indent();
 
160
        return status;
 
161
    }
 
162
#endif
 
163
 
 
164
    /* Perform NAT detection */
 
165
    if (pjsua_var.ua_cfg.stun_srv_cnt) {
 
166
        status = pjsua_detect_nat_type();
 
167
        if (status != PJ_SUCCESS) {
 
168
            PJ_PERROR(1,(THIS_FILE, status, "NAT type detection failed"));
 
169
        }
 
170
    }
 
171
 
 
172
    pj_log_pop_indent();
 
173
    return PJ_SUCCESS;
 
174
}
 
175
 
 
176
 
 
177
/*
 
178
 * Destroy pjsua media subsystem.
 
179
 */
 
180
pj_status_t pjsua_media_subsys_destroy(unsigned flags)
 
181
{
 
182
    PJ_UNUSED_ARG(flags);
 
183
 
 
184
    PJ_LOG(4,(THIS_FILE, "Shutting down media.."));
 
185
    pj_log_push_indent();
 
186
 
 
187
    if (pjsua_var.med_endpt) {
 
188
        /* Wait for media endpoint's worker threads to quit. */
 
189
        pjmedia_endpt_stop_threads(pjsua_var.med_endpt);
 
190
 
 
191
        pjsua_aud_subsys_destroy();
 
192
    }
 
193
 
 
194
#if 0
 
195
    // This part has been moved out to pjsua_destroy() (see also #1717).
 
196
    /* Close media transports */
 
197
    for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) {
 
198
        /* TODO: check if we're not allowed to send to network in the
 
199
         *       "flags", and if so do not do TURN allocation...
 
200
         */
 
201
        PJ_UNUSED_ARG(flags);
 
202
        pjsua_media_channel_deinit(i);
 
203
    }
 
204
#endif
 
205
 
 
206
    /* Destroy media endpoint. */
 
207
    if (pjsua_var.med_endpt) {
 
208
 
 
209
#       if PJMEDIA_HAS_VIDEO
 
210
            pjsua_vid_subsys_destroy();
 
211
#       endif
 
212
 
 
213
        pjmedia_endpt_destroy(pjsua_var.med_endpt);
 
214
        pjsua_var.med_endpt = NULL;
 
215
 
 
216
        /* Deinitialize sound subsystem */
 
217
        // Not necessary, as pjmedia_snd_deinit() should have been called
 
218
        // in pjmedia_endpt_destroy().
 
219
        //pjmedia_snd_deinit();
 
220
    }
 
221
 
 
222
    pj_log_pop_indent();
 
223
 
 
224
    return PJ_SUCCESS;
 
225
}
 
226
 
 
227
/*
 
228
 * Create RTP and RTCP socket pair, and possibly resolve their public
 
229
 * address via STUN.
 
230
 */
 
231
static pj_status_t create_rtp_rtcp_sock(pjsua_call_media *call_med,
 
232
                                        const pjsua_transport_config *cfg,
 
233
                                        pjmedia_sock_info *skinfo)
 
234
{
 
235
    enum {
 
236
        RTP_RETRY = 100
 
237
    };
 
238
    int i;
 
239
    pj_bool_t use_ipv6;
 
240
    int af;
 
241
    pj_sockaddr bound_addr;
 
242
    pj_sockaddr mapped_addr[2];
 
243
    pj_status_t status = PJ_SUCCESS;
 
244
    char addr_buf[PJ_INET6_ADDRSTRLEN+10];
 
245
    pjsua_acc *acc = &pjsua_var.acc[call_med->call->acc_id];
 
246
    pj_sock_t sock[2];
 
247
 
 
248
    use_ipv6 = (acc->cfg.ipv6_media_use != PJSUA_IPV6_DISABLED);
 
249
    af = use_ipv6 ? pj_AF_INET6() : pj_AF_INET();
 
250
 
 
251
    /* Make sure STUN server resolution has completed */
 
252
    if (!use_ipv6 && pjsua_sip_acc_is_using_stun(call_med->call->acc_id)) {
 
253
        status = resolve_stun_server(PJ_TRUE);
 
254
        if (status != PJ_SUCCESS) {
 
255
            pjsua_perror(THIS_FILE, "Error resolving STUN server", status);
 
256
            return status;
 
257
        }
 
258
    }
 
259
 
 
260
    if (acc->next_rtp_port == 0)
 
261
        acc->next_rtp_port = (pj_uint16_t)cfg->port;
 
262
 
 
263
    if (acc->next_rtp_port == 0)
 
264
        acc->next_rtp_port = (pj_uint16_t)DEFAULT_RTP_PORT;
 
265
 
 
266
    for (i=0; i<2; ++i)
 
267
        sock[i] = PJ_INVALID_SOCKET;
 
268
 
 
269
    pj_sockaddr_init(af, &bound_addr, NULL, 0);
 
270
    if (cfg->bound_addr.slen) {
 
271
        status = pj_sockaddr_set_str_addr(af, &bound_addr, &cfg->bound_addr);
 
272
        if (status != PJ_SUCCESS) {
 
273
            pjsua_perror(THIS_FILE, "Unable to resolve transport bind address",
 
274
                         status);
 
275
            return status;
 
276
        }
 
277
    }
 
278
 
 
279
    /* Loop retry to bind RTP and RTCP sockets. */
 
280
    for (i=0; i<RTP_RETRY; ++i, acc->next_rtp_port += 2) {
 
281
 
 
282
        if (cfg->port > 0 && cfg->port_range > 0 &&
 
283
            (acc->next_rtp_port > cfg->port + cfg->port_range ||
 
284
             acc->next_rtp_port < cfg->port))
 
285
        {
 
286
            acc->next_rtp_port = (pj_uint16_t)cfg->port;
 
287
        }
 
288
 
 
289
        /* Create RTP socket. */
 
290
        status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &sock[0]);
 
291
        if (status != PJ_SUCCESS) {
 
292
            pjsua_perror(THIS_FILE, "socket() error", status);
 
293
            return status;
 
294
        }
 
295
 
 
296
        /* Apply QoS to RTP socket, if specified */
 
297
        status = pj_sock_apply_qos2(sock[0], cfg->qos_type,
 
298
                                    &cfg->qos_params,
 
299
                                    2, THIS_FILE, "RTP socket");
 
300
 
 
301
        /* Bind RTP socket */
 
302
        pj_sockaddr_set_port(&bound_addr, acc->next_rtp_port);
 
303
        status=pj_sock_bind(sock[0], &bound_addr,
 
304
                            pj_sockaddr_get_len(&bound_addr));
 
305
        if (status != PJ_SUCCESS) {
 
306
            pj_sock_close(sock[0]);
 
307
            sock[0] = PJ_INVALID_SOCKET;
 
308
            continue;
 
309
        }
 
310
 
 
311
        /* Create RTCP socket. */
 
312
        status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &sock[1]);
 
313
        if (status != PJ_SUCCESS) {
 
314
            pjsua_perror(THIS_FILE, "socket() error", status);
 
315
            pj_sock_close(sock[0]);
 
316
            return status;
 
317
        }
 
318
 
 
319
        /* Apply QoS to RTCP socket, if specified */
 
320
        status = pj_sock_apply_qos2(sock[1], cfg->qos_type,
 
321
                                    &cfg->qos_params,
 
322
                                    2, THIS_FILE, "RTCP socket");
 
323
 
 
324
        /* Bind RTCP socket */
 
325
        pj_sockaddr_set_port(&bound_addr, (pj_uint16_t)(acc->next_rtp_port+1));
 
326
        status=pj_sock_bind(sock[1], &bound_addr,
 
327
                            pj_sockaddr_get_len(&bound_addr));
 
328
        if (status != PJ_SUCCESS) {
 
329
            pj_sock_close(sock[0]);
 
330
            sock[0] = PJ_INVALID_SOCKET;
 
331
 
 
332
            pj_sock_close(sock[1]);
 
333
            sock[1] = PJ_INVALID_SOCKET;
 
334
            continue;
 
335
        }
 
336
 
 
337
        /*
 
338
         * If we're configured to use STUN, then find out the mapped address,
 
339
         * and make sure that the mapped RTCP port is adjacent with the RTP.
 
340
         */
 
341
        if (!use_ipv6 && pjsua_sip_acc_is_using_stun(call_med->call->acc_id) &&
 
342
            pjsua_var.stun_srv.addr.sa_family != 0)
 
343
        {
 
344
            char ip_addr[32];
 
345
            pj_str_t stun_srv;
 
346
            pj_sockaddr_in resolved_addr[2];
 
347
            pjstun_setting stun_opt;
 
348
 
 
349
            pj_ansi_strcpy(ip_addr,
 
350
                           pj_inet_ntoa(pjsua_var.stun_srv.ipv4.sin_addr));
 
351
            stun_srv = pj_str(ip_addr);
 
352
 
 
353
            pj_bzero(&stun_opt, sizeof(stun_opt));
 
354
            stun_opt.use_stun2 = pjsua_var.ua_cfg.stun_map_use_stun2;
 
355
            stun_opt.srv1  = stun_opt.srv2  = stun_srv;
 
356
            stun_opt.port1 = stun_opt.port2 = 
 
357
                             pj_ntohs(pjsua_var.stun_srv.ipv4.sin_port);
 
358
            status=pjstun_get_mapped_addr2(&pjsua_var.cp.factory, &stun_opt,
 
359
                                           2, sock, resolved_addr);
 
360
#if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \
 
361
            PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0
 
362
            /* Handle EPIPE (Broken Pipe) error, which happens on UDP socket
 
363
             * after app wakes up from suspended state. In this case, simply
 
364
             * just retry.
 
365
             * P.S.: The magic status is PJ_STATUS_FROM_OS(EPIPE)
 
366
             */
 
367
            if (status == 120032) {
 
368
                PJ_LOG(4,(THIS_FILE, "Got EPIPE error, retrying.."));
 
369
                pj_sock_close(sock[0]);
 
370
                sock[0] = PJ_INVALID_SOCKET;
 
371
 
 
372
                pj_sock_close(sock[1]);
 
373
                sock[1] = PJ_INVALID_SOCKET;
 
374
 
 
375
                continue;
 
376
            }
 
377
            else
 
378
#endif
 
379
            if (status != PJ_SUCCESS) {
 
380
                pjsua_perror(THIS_FILE, "STUN resolve error", status);
 
381
                goto on_error;
 
382
            }
 
383
 
 
384
            pj_sockaddr_cp(&mapped_addr[0], &resolved_addr[0]);
 
385
            pj_sockaddr_cp(&mapped_addr[1], &resolved_addr[1]);
 
386
 
 
387
#if PJSUA_REQUIRE_CONSECUTIVE_RTCP_PORT
 
388
            if (pj_sockaddr_get_port(&mapped_addr[1]) ==
 
389
                pj_sockaddr_get_port(&mapped_addr[0])+1)
 
390
            {
 
391
                /* Success! */
 
392
                break;
 
393
            }
 
394
 
 
395
            pj_sock_close(sock[0]);
 
396
            sock[0] = PJ_INVALID_SOCKET;
 
397
 
 
398
            pj_sock_close(sock[1]);
 
399
            sock[1] = PJ_INVALID_SOCKET;
 
400
#else
 
401
            if (pj_sockaddr_get_port(&mapped_addr[1]) !=
 
402
                pj_sockaddr_get_port(&mapped_addr[0])+1)
 
403
            {
 
404
                PJ_LOG(4,(THIS_FILE,
 
405
                          "Note: STUN mapped RTCP port %d is not adjacent"
 
406
                          " to RTP port %d",
 
407
                          pj_sockaddr_get_port(&mapped_addr[1]),
 
408
                          pj_sockaddr_get_port(&mapped_addr[0])));
 
409
            }
 
410
            /* Success! */
 
411
            break;
 
412
#endif
 
413
 
 
414
        } else if (cfg->public_addr.slen) {
 
415
 
 
416
            status = pj_sockaddr_init(af, &mapped_addr[0], &cfg->public_addr,
 
417
                                      (pj_uint16_t)acc->next_rtp_port);
 
418
            if (status != PJ_SUCCESS)
 
419
                goto on_error;
 
420
 
 
421
            status = pj_sockaddr_init(af, &mapped_addr[1], &cfg->public_addr,
 
422
                                      (pj_uint16_t)(acc->next_rtp_port+1));
 
423
            if (status != PJ_SUCCESS)
 
424
                goto on_error;
 
425
 
 
426
            break;
 
427
 
 
428
        } else {
 
429
            if (acc->cfg.allow_sdp_nat_rewrite && acc->reg_mapped_addr.slen) {
 
430
                pj_status_t status;
 
431
 
 
432
                /* Take the address from mapped addr as seen by registrar */
 
433
                status = pj_sockaddr_set_str_addr(af, &bound_addr,
 
434
                                                  &acc->reg_mapped_addr);
 
435
                if (status != PJ_SUCCESS) {
 
436
                    /* just leave bound_addr with whatever it was
 
437
                    pj_bzero(pj_sockaddr_get_addr(&bound_addr),
 
438
                             pj_sockaddr_get_addr_len(&bound_addr));
 
439
                     */
 
440
                }
 
441
            }
 
442
 
 
443
            if (!pj_sockaddr_has_addr(&bound_addr)) {
 
444
                pj_sockaddr addr;
 
445
 
 
446
                /* Get local IP address. */
 
447
                status = pj_gethostip(af, &addr);
 
448
                if (status != PJ_SUCCESS)
 
449
                    goto on_error;
 
450
 
 
451
                pj_sockaddr_copy_addr(&bound_addr, &addr);
 
452
            }
 
453
 
 
454
            for (i=0; i<2; ++i) {
 
455
                pj_sockaddr_init(af, &mapped_addr[i], NULL, 0);
 
456
                pj_sockaddr_copy_addr(&mapped_addr[i], &bound_addr);
 
457
                pj_sockaddr_set_port(&mapped_addr[i],
 
458
                                     (pj_uint16_t)(acc->next_rtp_port+i));
 
459
            }
 
460
 
 
461
            break;
 
462
        }
 
463
    }
 
464
 
 
465
    if (sock[0] == PJ_INVALID_SOCKET) {
 
466
        PJ_LOG(1,(THIS_FILE,
 
467
                  "Unable to find appropriate RTP/RTCP ports combination"));
 
468
        goto on_error;
 
469
    }
 
470
 
 
471
 
 
472
    skinfo->rtp_sock = sock[0];
 
473
    pj_sockaddr_cp(&skinfo->rtp_addr_name, &mapped_addr[0]);
 
474
 
 
475
    skinfo->rtcp_sock = sock[1];
 
476
    pj_sockaddr_cp(&skinfo->rtcp_addr_name, &mapped_addr[1]);
 
477
 
 
478
    PJ_LOG(4,(THIS_FILE, "RTP socket reachable at %s",
 
479
              pj_sockaddr_print(&skinfo->rtp_addr_name, addr_buf,
 
480
                                sizeof(addr_buf), 3)));
 
481
    PJ_LOG(4,(THIS_FILE, "RTCP socket reachable at %s",
 
482
              pj_sockaddr_print(&skinfo->rtcp_addr_name, addr_buf,
 
483
                                sizeof(addr_buf), 3)));
 
484
 
 
485
    acc->next_rtp_port += 2;
 
486
    return PJ_SUCCESS;
 
487
 
 
488
on_error:
 
489
    for (i=0; i<2; ++i) {
 
490
        if (sock[i] != PJ_INVALID_SOCKET)
 
491
            pj_sock_close(sock[i]);
 
492
    }
 
493
    return status;
 
494
}
 
495
 
 
496
/* Create normal UDP media transports */
 
497
static pj_status_t create_udp_media_transport(const pjsua_transport_config *cfg,
 
498
                                              pjsua_call_media *call_med)
 
499
{
 
500
    pjmedia_sock_info skinfo;
 
501
    pj_status_t status;
 
502
 
 
503
    status = create_rtp_rtcp_sock(call_med, cfg, &skinfo);
 
504
    if (status != PJ_SUCCESS) {
 
505
        pjsua_perror(THIS_FILE, "Unable to create RTP/RTCP socket",
 
506
                     status);
 
507
        goto on_error;
 
508
    }
 
509
 
 
510
    status = pjmedia_transport_udp_attach(pjsua_var.med_endpt, NULL,
 
511
                                          &skinfo, 0, &call_med->tp);
 
512
    if (status != PJ_SUCCESS) {
 
513
        pjsua_perror(THIS_FILE, "Unable to create media transport",
 
514
                     status);
 
515
        goto on_error;
 
516
    }
 
517
 
 
518
    pjmedia_transport_simulate_lost(call_med->tp, PJMEDIA_DIR_ENCODING,
 
519
                                    pjsua_var.media_cfg.tx_drop_pct);
 
520
 
 
521
    pjmedia_transport_simulate_lost(call_med->tp, PJMEDIA_DIR_DECODING,
 
522
                                    pjsua_var.media_cfg.rx_drop_pct);
 
523
 
 
524
    call_med->tp_ready = PJ_SUCCESS;
 
525
 
 
526
    return PJ_SUCCESS;
 
527
 
 
528
on_error:
 
529
    if (call_med->tp)
 
530
        pjmedia_transport_close(call_med->tp);
 
531
 
 
532
    return status;
 
533
}
 
534
 
 
535
#if DISABLED_FOR_TICKET_1185
 
536
/* Create normal UDP media transports */
 
537
static pj_status_t create_udp_media_transports(pjsua_transport_config *cfg)
 
538
{
 
539
    unsigned i;
 
540
    pj_status_t status;
 
541
 
 
542
    for (i=0; i < pjsua_var.ua_cfg.max_calls; ++i) {
 
543
        pjsua_call *call = &pjsua_var.calls[i];
 
544
        unsigned strm_idx;
 
545
 
 
546
        for (strm_idx=0; strm_idx < call->med_cnt; ++strm_idx) {
 
547
            pjsua_call_media *call_med = &call->media[strm_idx];
 
548
 
 
549
            status = create_udp_media_transport(cfg, &call_med->tp);
 
550
            if (status != PJ_SUCCESS)
 
551
                goto on_error;
 
552
        }
 
553
    }
 
554
 
 
555
    return PJ_SUCCESS;
 
556
 
 
557
on_error:
 
558
    for (i=0; i < pjsua_var.ua_cfg.max_calls; ++i) {
 
559
        pjsua_call *call = &pjsua_var.calls[i];
 
560
        unsigned strm_idx;
 
561
 
 
562
        for (strm_idx=0; strm_idx < call->med_cnt; ++strm_idx) {
 
563
            pjsua_call_media *call_med = &call->media[strm_idx];
 
564
 
 
565
            if (call_med->tp) {
 
566
                pjmedia_transport_close(call_med->tp);
 
567
                call_med->tp = NULL;
 
568
            }
 
569
        }
 
570
    }
 
571
    return status;
 
572
}
 
573
#endif
 
574
 
 
575
/* Deferred callback to notify ICE init complete */
 
576
static void ice_init_complete_cb(void *user_data)
 
577
{
 
578
    pjsua_call_media *call_med = (pjsua_call_media*)user_data;
 
579
 
 
580
    if (call_med->call == NULL)
 
581
        return;
 
582
 
 
583
    /* No need to acquire_call() if we only change the tp_ready flag
 
584
     * (i.e. transport is being created synchronously). Otherwise
 
585
     * calling acquire_call() here may cause deadlock. See
 
586
     * https://trac.pjsip.org/repos/ticket/1578
 
587
     */
 
588
    call_med->tp_ready = call_med->tp_result;
 
589
 
 
590
    if (call_med->med_create_cb) {
 
591
        pjsua_call *call = NULL;
 
592
        pjsip_dialog *dlg = NULL;
 
593
 
 
594
        if (acquire_call("ice_init_complete_cb", call_med->call->index,
 
595
                         &call, &dlg) != PJ_SUCCESS)
 
596
        {
 
597
            /* Call have been terminated */
 
598
            return;
 
599
        }
 
600
 
 
601
        (*call_med->med_create_cb)(call_med, call_med->tp_ready,
 
602
                                   call_med->call->secure_level, NULL);
 
603
 
 
604
        if (dlg)
 
605
            pjsip_dlg_dec_lock(dlg);
 
606
    }
 
607
}
 
608
 
 
609
/* Deferred callback to notify ICE negotiation failure */
 
610
static void ice_failed_nego_cb(void *user_data)
 
611
{
 
612
    int call_id = (int)(pj_ssize_t)user_data;
 
613
    pjsua_call *call = NULL;
 
614
    pjsip_dialog *dlg = NULL;
 
615
 
 
616
    if (acquire_call("ice_failed_nego_cb", call_id,
 
617
                     &call, &dlg) != PJ_SUCCESS)
 
618
    {
 
619
        /* Call have been terminated */
 
620
        return;
 
621
    }
 
622
 
 
623
    pjsua_var.ua_cfg.cb.on_call_media_state(call_id);
 
624
 
 
625
    if (dlg)
 
626
        pjsip_dlg_dec_lock(dlg);
 
627
 
 
628
}
 
629
 
 
630
/* This callback is called when ICE negotiation completes */
 
631
static void on_ice_complete(pjmedia_transport *tp, 
 
632
                            pj_ice_strans_op op,
 
633
                            pj_status_t result)
 
634
{
 
635
    pjsua_call_media *call_med = (pjsua_call_media*)tp->user_data;
 
636
    pjsua_call *call;
 
637
 
 
638
    if (!call_med)
 
639
        return;
 
640
 
 
641
    call = call_med->call;
 
642
    
 
643
    switch (op) {
 
644
    case PJ_ICE_STRANS_OP_INIT:
 
645
        call_med->tp_result = result;
 
646
        pjsua_schedule_timer2(&ice_init_complete_cb, call_med, 1);
 
647
        break;
 
648
    case PJ_ICE_STRANS_OP_NEGOTIATION:
 
649
        if (result == PJ_SUCCESS) {
 
650
            /* Update RTP address */
 
651
            pjmedia_transport_info tpinfo;
 
652
            pjmedia_transport_info_init(&tpinfo);
 
653
            pjmedia_transport_get_info(call_med->tp, &tpinfo);
 
654
            pj_sockaddr_cp(&call_med->rtp_addr, &tpinfo.sock_info.rtp_addr_name);
 
655
        } else {
 
656
            call_med->state = PJSUA_CALL_MEDIA_ERROR;
 
657
            call_med->dir = PJMEDIA_DIR_NONE;
 
658
            if (call && pjsua_var.ua_cfg.cb.on_call_media_state) {
 
659
                /* Defer the callback to a timer */
 
660
                pjsua_schedule_timer2(&ice_failed_nego_cb,
 
661
                                      (void*)(pj_ssize_t)call->index, 1);
 
662
            }
 
663
        }
 
664
        /* Check if default ICE transport address is changed */
 
665
        call->reinv_ice_sent = PJ_FALSE;
 
666
        pjsua_call_schedule_reinvite_check(call, 0);
 
667
        break;
 
668
    case PJ_ICE_STRANS_OP_KEEP_ALIVE:
 
669
        if (result != PJ_SUCCESS) {
 
670
            PJ_PERROR(4,(THIS_FILE, result,
 
671
                         "ICE keep alive failure for transport %d:%d",
 
672
                         call->index, call_med->idx));
 
673
        }
 
674
        if (pjsua_var.ua_cfg.cb.on_call_media_transport_state) {
 
675
            pjsua_med_tp_state_info info;
 
676
 
 
677
            pj_bzero(&info, sizeof(info));
 
678
            info.med_idx = call_med->idx;
 
679
            info.state = call_med->tp_st;
 
680
            info.status = result;
 
681
            info.ext_info = &op;
 
682
            (*pjsua_var.ua_cfg.cb.on_call_media_transport_state)(
 
683
                call->index, &info);
 
684
        }
 
685
        if (pjsua_var.ua_cfg.cb.on_ice_transport_error) {
 
686
            pjsua_call_id id = call->index;
 
687
            (*pjsua_var.ua_cfg.cb.on_ice_transport_error)(id, op, result,
 
688
                                                          NULL);
 
689
        }
 
690
        break;
 
691
    }
 
692
}
 
693
 
 
694
 
 
695
/* Parse "HOST:PORT" format */
 
696
static pj_status_t parse_host_port(const pj_str_t *host_port,
 
697
                                   pj_str_t *host, pj_uint16_t *port)
 
698
{
 
699
    pj_str_t str_port;
 
700
 
 
701
    str_port.ptr = pj_strchr(host_port, ':');
 
702
    if (str_port.ptr != NULL) {
 
703
        int iport;
 
704
 
 
705
        host->ptr = host_port->ptr;
 
706
        host->slen = (str_port.ptr - host->ptr);
 
707
        str_port.ptr++;
 
708
        str_port.slen = host_port->slen - host->slen - 1;
 
709
        iport = (int)pj_strtoul(&str_port);
 
710
        if (iport < 1 || iport > 65535)
 
711
            return PJ_EINVAL;
 
712
        *port = (pj_uint16_t)iport;
 
713
    } else {
 
714
        *host = *host_port;
 
715
        *port = 0;
 
716
    }
 
717
 
 
718
    return PJ_SUCCESS;
 
719
}
 
720
 
 
721
/* Create ICE media transports (when ice is enabled) */
 
722
static pj_status_t create_ice_media_transport(
 
723
                                const pjsua_transport_config *cfg,
 
724
                                pjsua_call_media *call_med,
 
725
                                pj_bool_t async)
 
726
{
 
727
    char stunip[PJ_INET6_ADDRSTRLEN];
 
728
    pjsua_acc_config *acc_cfg;
 
729
    pj_ice_strans_cfg ice_cfg;
 
730
    pjmedia_ice_cb ice_cb;
 
731
    char name[32];
 
732
    unsigned comp_cnt;
 
733
    pj_status_t status;
 
734
 
 
735
    acc_cfg = &pjsua_var.acc[call_med->call->acc_id].cfg;
 
736
 
 
737
    /* Make sure STUN server resolution has completed */
 
738
    status = resolve_stun_server(PJ_TRUE);
 
739
    if (status != PJ_SUCCESS) {
 
740
        pjsua_perror(THIS_FILE, "Error resolving STUN server", status);
 
741
        return status;
 
742
    }
 
743
 
 
744
    /* Create ICE stream transport configuration */
 
745
    pj_ice_strans_cfg_default(&ice_cfg);
 
746
    pj_stun_config_init(&ice_cfg.stun_cfg, &pjsua_var.cp.factory, 0,
 
747
                        pjsip_endpt_get_ioqueue(pjsua_var.endpt),
 
748
                        pjsip_endpt_get_timer_heap(pjsua_var.endpt));
 
749
    
 
750
    ice_cfg.af = pj_AF_INET();
 
751
    ice_cfg.resolver = pjsua_var.resolver;
 
752
    
 
753
    ice_cfg.opt = acc_cfg->ice_cfg.ice_opt;
 
754
 
 
755
    /* Configure STUN settings */
 
756
    if (pj_sockaddr_has_addr(&pjsua_var.stun_srv)) {
 
757
        pj_sockaddr_print(&pjsua_var.stun_srv, stunip, sizeof(stunip), 0);
 
758
        ice_cfg.stun.server = pj_str(stunip);
 
759
        ice_cfg.stun.port = pj_sockaddr_get_port(&pjsua_var.stun_srv);
 
760
    }
 
761
    if (acc_cfg->ice_cfg.ice_max_host_cands >= 0)
 
762
        ice_cfg.stun.max_host_cands = acc_cfg->ice_cfg.ice_max_host_cands;
 
763
 
 
764
    /* Copy binding port setting to STUN setting */
 
765
    pj_sockaddr_init(ice_cfg.af, &ice_cfg.stun.cfg.bound_addr,
 
766
                     &cfg->bound_addr, (pj_uint16_t)cfg->port);
 
767
    ice_cfg.stun.cfg.port_range = (pj_uint16_t)cfg->port_range;
 
768
    if (cfg->port != 0 && ice_cfg.stun.cfg.port_range == 0)
 
769
        ice_cfg.stun.cfg.port_range = 
 
770
                                 (pj_uint16_t)(pjsua_var.ua_cfg.max_calls * 10);
 
771
 
 
772
    /* Copy QoS setting to STUN setting */
 
773
    ice_cfg.stun.cfg.qos_type = cfg->qos_type;
 
774
    pj_memcpy(&ice_cfg.stun.cfg.qos_params, &cfg->qos_params,
 
775
              sizeof(cfg->qos_params));
 
776
 
 
777
    /* Configure TURN settings */
 
778
    if (acc_cfg->turn_cfg.enable_turn) {
 
779
        status = parse_host_port(&acc_cfg->turn_cfg.turn_server,
 
780
                                 &ice_cfg.turn.server,
 
781
                                 &ice_cfg.turn.port);
 
782
        if (status != PJ_SUCCESS || ice_cfg.turn.server.slen == 0) {
 
783
            PJ_LOG(1,(THIS_FILE, "Invalid TURN server setting"));
 
784
            return PJ_EINVAL;
 
785
        }
 
786
        if (ice_cfg.turn.port == 0)
 
787
            ice_cfg.turn.port = 3479;
 
788
        ice_cfg.turn.conn_type = acc_cfg->turn_cfg.turn_conn_type;
 
789
        pj_memcpy(&ice_cfg.turn.auth_cred, 
 
790
                  &acc_cfg->turn_cfg.turn_auth_cred,
 
791
                  sizeof(ice_cfg.turn.auth_cred));
 
792
 
 
793
        /* Copy QoS setting to TURN setting */
 
794
        ice_cfg.turn.cfg.qos_type = cfg->qos_type;
 
795
        pj_memcpy(&ice_cfg.turn.cfg.qos_params, &cfg->qos_params,
 
796
                  sizeof(cfg->qos_params));
 
797
 
 
798
        /* Copy binding port setting to TURN setting */
 
799
        pj_sockaddr_init(ice_cfg.af, &ice_cfg.turn.cfg.bound_addr,
 
800
                         &cfg->bound_addr, (pj_uint16_t)cfg->port);
 
801
        ice_cfg.turn.cfg.port_range = (pj_uint16_t)cfg->port_range;
 
802
        if (cfg->port != 0 && ice_cfg.turn.cfg.port_range == 0)
 
803
            ice_cfg.turn.cfg.port_range = 
 
804
                                 (pj_uint16_t)(pjsua_var.ua_cfg.max_calls * 10);
 
805
    }
 
806
 
 
807
    /* Configure packet size for STUN and TURN sockets */
 
808
    ice_cfg.stun.cfg.max_pkt_size = PJMEDIA_MAX_MRU;
 
809
    ice_cfg.turn.cfg.max_pkt_size = PJMEDIA_MAX_MRU;
 
810
 
 
811
    pj_bzero(&ice_cb, sizeof(pjmedia_ice_cb));
 
812
    ice_cb.on_ice_complete = &on_ice_complete;
 
813
    pj_ansi_snprintf(name, sizeof(name), "icetp%02d", call_med->idx);
 
814
    call_med->tp_ready = PJ_EPENDING;
 
815
 
 
816
    comp_cnt = 1;
 
817
    if (PJMEDIA_ADVERTISE_RTCP && !acc_cfg->ice_cfg.ice_no_rtcp)
 
818
        ++comp_cnt;
 
819
 
 
820
    status = pjmedia_ice_create3(pjsua_var.med_endpt, name, comp_cnt,
 
821
                                 &ice_cfg, &ice_cb, 0, call_med,
 
822
                                 &call_med->tp);
 
823
    if (status != PJ_SUCCESS) {
 
824
        pjsua_perror(THIS_FILE, "Unable to create ICE media transport",
 
825
                     status);
 
826
        goto on_error;
 
827
    }
 
828
 
 
829
    /* Wait until transport is initialized, or time out */
 
830
    if (!async) {
 
831
        pj_bool_t has_pjsua_lock = PJSUA_LOCK_IS_LOCKED();
 
832
        pjsip_dialog *dlg = call_med->call->inv ?
 
833
                                call_med->call->inv->dlg : NULL;
 
834
        if (has_pjsua_lock)
 
835
            PJSUA_UNLOCK();
 
836
        if (dlg) {
 
837
            /* Don't lock otherwise deadlock:
 
838
             * https://trac.pjsip.org/repos/ticket/1737
 
839
             */
 
840
            ++dlg->sess_count;
 
841
            pjsip_dlg_dec_lock(dlg);
 
842
        }
 
843
        while (call_med->tp_ready == PJ_EPENDING) {
 
844
            pjsua_handle_events(100);
 
845
        }
 
846
        if (dlg) {
 
847
            pjsip_dlg_inc_lock(dlg);
 
848
            --dlg->sess_count;
 
849
        }
 
850
        if (has_pjsua_lock)
 
851
            PJSUA_LOCK();
 
852
    }
 
853
 
 
854
    if (async && call_med->tp_ready == PJ_EPENDING) {
 
855
        return PJ_EPENDING;
 
856
    } else if (call_med->tp_ready != PJ_SUCCESS) {
 
857
        pjsua_perror(THIS_FILE, "Error initializing ICE media transport",
 
858
                     call_med->tp_ready);
 
859
        status = call_med->tp_ready;
 
860
        goto on_error;
 
861
    }
 
862
 
 
863
    pjmedia_transport_simulate_lost(call_med->tp, PJMEDIA_DIR_ENCODING,
 
864
                                    pjsua_var.media_cfg.tx_drop_pct);
 
865
 
 
866
    pjmedia_transport_simulate_lost(call_med->tp, PJMEDIA_DIR_DECODING,
 
867
                                    pjsua_var.media_cfg.rx_drop_pct);
 
868
    
 
869
    return PJ_SUCCESS;
 
870
 
 
871
on_error:
 
872
    if (call_med->tp != NULL) {
 
873
        pjmedia_transport_close(call_med->tp);
 
874
        call_med->tp = NULL;
 
875
    }
 
876
 
 
877
    return status;
 
878
}
 
879
 
 
880
#if DISABLED_FOR_TICKET_1185
 
881
/* Create ICE media transports (when ice is enabled) */
 
882
static pj_status_t create_ice_media_transports(pjsua_transport_config *cfg)
 
883
{
 
884
    unsigned i;
 
885
    pj_status_t status;
 
886
 
 
887
    for (i=0; i < pjsua_var.ua_cfg.max_calls; ++i) {
 
888
        pjsua_call *call = &pjsua_var.calls[i];
 
889
        unsigned strm_idx;
 
890
 
 
891
        for (strm_idx=0; strm_idx < call->med_cnt; ++strm_idx) {
 
892
            pjsua_call_media *call_med = &call->media[strm_idx];
 
893
 
 
894
            status = create_ice_media_transport(cfg, call_med);
 
895
            if (status != PJ_SUCCESS)
 
896
                goto on_error;
 
897
        }
 
898
    }
 
899
 
 
900
    return PJ_SUCCESS;
 
901
 
 
902
on_error:
 
903
    for (i=0; i < pjsua_var.ua_cfg.max_calls; ++i) {
 
904
        pjsua_call *call = &pjsua_var.calls[i];
 
905
        unsigned strm_idx;
 
906
 
 
907
        for (strm_idx=0; strm_idx < call->med_cnt; ++strm_idx) {
 
908
            pjsua_call_media *call_med = &call->media[strm_idx];
 
909
 
 
910
            if (call_med->tp) {
 
911
                pjmedia_transport_close(call_med->tp);
 
912
                call_med->tp = NULL;
 
913
            }
 
914
        }
 
915
    }
 
916
    return status;
 
917
}
 
918
#endif
 
919
 
 
920
#if DISABLED_FOR_TICKET_1185
 
921
/*
 
922
 * Create media transports for all the calls. This function creates
 
923
 * one UDP media transport for each call.
 
924
 */
 
925
PJ_DEF(pj_status_t) pjsua_media_transports_create(
 
926
                        const pjsua_transport_config *app_cfg)
 
927
{
 
928
    pjsua_transport_config cfg;
 
929
    unsigned i;
 
930
    pj_status_t status;
 
931
 
 
932
 
 
933
    /* Make sure pjsua_init() has been called */
 
934
    PJ_ASSERT_RETURN(pjsua_var.ua_cfg.max_calls>0, PJ_EINVALIDOP);
 
935
 
 
936
    PJSUA_LOCK();
 
937
 
 
938
    /* Delete existing media transports */
 
939
    for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) {
 
940
        pjsua_call *call = &pjsua_var.calls[i];
 
941
        unsigned strm_idx;
 
942
 
 
943
        for (strm_idx=0; strm_idx < call->med_cnt; ++strm_idx) {
 
944
            pjsua_call_media *call_med = &call->media[strm_idx];
 
945
 
 
946
            if (call_med->tp && call_med->tp_auto_del) {
 
947
                pjmedia_transport_close(call_med->tp);
 
948
                call_med->tp = NULL;
 
949
                call_med->tp_orig = NULL;
 
950
            }
 
951
        }
 
952
    }
 
953
 
 
954
    /* Copy config */
 
955
    pjsua_transport_config_dup(pjsua_var.pool, &cfg, app_cfg);
 
956
 
 
957
    /* Create the transports */
 
958
    if (pjsua_var.ice_cfg.enable_ice) {
 
959
        status = create_ice_media_transports(&cfg);
 
960
    } else {
 
961
        status = create_udp_media_transports(&cfg);
 
962
    }
 
963
 
 
964
    /* Set media transport auto_delete to True */
 
965
    for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) {
 
966
        pjsua_call *call = &pjsua_var.calls[i];
 
967
        unsigned strm_idx;
 
968
 
 
969
        for (strm_idx=0; strm_idx < call->med_cnt; ++strm_idx) {
 
970
            pjsua_call_media *call_med = &call->media[strm_idx];
 
971
 
 
972
            call_med->tp_auto_del = PJ_TRUE;
 
973
        }
 
974
    }
 
975
 
 
976
    PJSUA_UNLOCK();
 
977
 
 
978
    return status;
 
979
}
 
980
 
 
981
/*
 
982
 * Attach application's created media transports.
 
983
 */
 
984
PJ_DEF(pj_status_t) pjsua_media_transports_attach(pjsua_media_transport tp[],
 
985
                                                  unsigned count,
 
986
                                                  pj_bool_t auto_delete)
 
987
{
 
988
    unsigned i;
 
989
 
 
990
    PJ_ASSERT_RETURN(tp && count==pjsua_var.ua_cfg.max_calls, PJ_EINVAL);
 
991
 
 
992
    /* Assign the media transports */
 
993
    for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) {
 
994
        pjsua_call *call = &pjsua_var.calls[i];
 
995
        unsigned strm_idx;
 
996
 
 
997
        for (strm_idx=0; strm_idx < call->med_cnt; ++strm_idx) {
 
998
            pjsua_call_media *call_med = &call->media[strm_idx];
 
999
 
 
1000
            if (call_med->tp && call_med->tp_auto_del) {
 
1001
                pjmedia_transport_close(call_med->tp);
 
1002
                call_med->tp = NULL;
 
1003
                call_med->tp_orig = NULL;
 
1004
            }
 
1005
        }
 
1006
 
 
1007
        PJ_TODO(remove_pjsua_media_transports_attach);
 
1008
 
 
1009
        call->media[0].tp = tp[i].transport;
 
1010
        call->media[0].tp_auto_del = auto_delete;
 
1011
    }
 
1012
 
 
1013
    return PJ_SUCCESS;
 
1014
}
 
1015
#endif
 
1016
 
 
1017
/* Go through the list of media in the SDP, find acceptable media, and
 
1018
 * sort them based on the "quality" of the media, and store the indexes
 
1019
 * in the specified array. Media with the best quality will be listed
 
1020
 * first in the array. The quality factors considered currently is
 
1021
 * encryption.
 
1022
 */
 
1023
static void sort_media(const pjmedia_sdp_session *sdp,
 
1024
                       const pj_str_t *type,
 
1025
                       pjmedia_srtp_use use_srtp,
 
1026
                       pj_uint8_t midx[],
 
1027
                       unsigned *p_count,
 
1028
                       unsigned *p_total_count)
 
1029
{
 
1030
    unsigned i;
 
1031
    unsigned count = 0;
 
1032
    int score[PJSUA_MAX_CALL_MEDIA];
 
1033
 
 
1034
    pj_assert(*p_count >= PJSUA_MAX_CALL_MEDIA);
 
1035
    pj_assert(*p_total_count >= PJSUA_MAX_CALL_MEDIA);
 
1036
 
 
1037
    *p_count = 0;
 
1038
    *p_total_count = 0;
 
1039
    for (i=0; i<PJSUA_MAX_CALL_MEDIA; ++i)
 
1040
        score[i] = 1;
 
1041
 
 
1042
    /* Score each media */
 
1043
    for (i=0; i<sdp->media_count && count<PJSUA_MAX_CALL_MEDIA; ++i) {
 
1044
        const pjmedia_sdp_media *m = sdp->media[i];
 
1045
        const pjmedia_sdp_conn *c;
 
1046
 
 
1047
        /* Skip different media */
 
1048
        if (pj_stricmp(&m->desc.media, type) != 0) {
 
1049
            score[count++] = -22000;
 
1050
            continue;
 
1051
        }
 
1052
 
 
1053
        c = m->conn? m->conn : sdp->conn;
 
1054
 
 
1055
        /* Supported transports */
 
1056
        if (pj_stricmp2(&m->desc.transport, "RTP/SAVP")==0) {
 
1057
            switch (use_srtp) {
 
1058
            case PJMEDIA_SRTP_MANDATORY:
 
1059
            case PJMEDIA_SRTP_OPTIONAL:
 
1060
                ++score[i];
 
1061
                break;
 
1062
            case PJMEDIA_SRTP_DISABLED:
 
1063
                //--score[i];
 
1064
                score[i] -= 5;
 
1065
                break;
 
1066
            }
 
1067
        } else if (pj_stricmp2(&m->desc.transport, "RTP/AVP")==0) {
 
1068
            switch (use_srtp) {
 
1069
            case PJMEDIA_SRTP_MANDATORY:
 
1070
                //--score[i];
 
1071
                score[i] -= 5;
 
1072
                break;
 
1073
            case PJMEDIA_SRTP_OPTIONAL:
 
1074
                /* No change in score */
 
1075
                break;
 
1076
            case PJMEDIA_SRTP_DISABLED:
 
1077
                ++score[i];
 
1078
                break;
 
1079
            }
 
1080
        } else {
 
1081
            score[i] -= 10;
 
1082
        }
 
1083
 
 
1084
        /* Is media disabled? */
 
1085
        if (m->desc.port == 0)
 
1086
            score[i] -= 10;
 
1087
 
 
1088
        /* Is media inactive? */
 
1089
        if (pjmedia_sdp_media_find_attr2(m, "inactive", NULL) ||
 
1090
            pj_strcmp2(&c->addr, "0.0.0.0") == 0)
 
1091
        {
 
1092
            //score[i] -= 10;
 
1093
            score[i] -= 1;
 
1094
        }
 
1095
 
 
1096
        ++count;
 
1097
    }
 
1098
 
 
1099
    /* Created sorted list based on quality */
 
1100
    for (i=0; i<count; ++i) {
 
1101
        unsigned j;
 
1102
        int best = 0;
 
1103
 
 
1104
        for (j=1; j<count; ++j) {
 
1105
            if (score[j] > score[best])
 
1106
                best = j;
 
1107
        }
 
1108
        /* Don't put media with negative score, that media is unacceptable
 
1109
         * for us.
 
1110
         */
 
1111
        midx[i] = (pj_uint8_t)best;
 
1112
        if (score[best] >= 0)
 
1113
            (*p_count)++;
 
1114
        if (score[best] > -22000)
 
1115
            (*p_total_count)++;
 
1116
 
 
1117
        score[best] = -22000;
 
1118
 
 
1119
    }
 
1120
}
 
1121
 
 
1122
/* Callback to receive media events */
 
1123
pj_status_t call_media_on_event(pjmedia_event *event,
 
1124
                                void *user_data)
 
1125
{
 
1126
    pjsua_call_media *call_med = (pjsua_call_media*)user_data;
 
1127
    pjsua_call *call = call_med->call;
 
1128
    pj_status_t status = PJ_SUCCESS;
 
1129
  
 
1130
    switch(event->type) {
 
1131
        case PJMEDIA_EVENT_KEYFRAME_MISSING:
 
1132
            if (call->opt.req_keyframe_method & PJSUA_VID_REQ_KEYFRAME_SIP_INFO)
 
1133
            {
 
1134
                pj_timestamp now;
 
1135
 
 
1136
                pj_get_timestamp(&now);
 
1137
                if (pj_elapsed_msec(&call_med->last_req_keyframe, &now) >=
 
1138
                    PJSUA_VID_REQ_KEYFRAME_INTERVAL)
 
1139
                {
 
1140
                    pjsua_msg_data msg_data;
 
1141
                    const pj_str_t SIP_INFO = {"INFO", 4};
 
1142
                    const char *BODY_TYPE = "application/media_control+xml";
 
1143
                    const char *BODY =
 
1144
                        "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
 
1145
                        "<media_control><vc_primitive><to_encoder>"
 
1146
                        "<picture_fast_update/>"
 
1147
                        "</to_encoder></vc_primitive></media_control>";
 
1148
 
 
1149
                    PJ_LOG(4,(THIS_FILE, 
 
1150
                              "Sending video keyframe request via SIP INFO"));
 
1151
 
 
1152
                    pjsua_msg_data_init(&msg_data);
 
1153
                    pj_cstr(&msg_data.content_type, BODY_TYPE);
 
1154
                    pj_cstr(&msg_data.msg_body, BODY);
 
1155
                    status = pjsua_call_send_request(call->index, &SIP_INFO, 
 
1156
                                                     &msg_data);
 
1157
                    if (status != PJ_SUCCESS) {
 
1158
                        pj_perror(3, THIS_FILE, status,
 
1159
                                  "Failed requesting keyframe via SIP INFO");
 
1160
                    } else {
 
1161
                        call_med->last_req_keyframe = now;
 
1162
                    }
 
1163
                }
 
1164
            }
 
1165
            break;
 
1166
 
 
1167
        default:
 
1168
            break;
 
1169
    }
 
1170
 
 
1171
    if (pjsua_var.ua_cfg.cb.on_call_media_event && call) {
 
1172
        (*pjsua_var.ua_cfg.cb.on_call_media_event)(call->index,
 
1173
                                                   call_med->idx, event);
 
1174
    }
 
1175
 
 
1176
    return status;
 
1177
}
 
1178
 
 
1179
/* Set media transport state and notify the application via the callback. */
 
1180
void pjsua_set_media_tp_state(pjsua_call_media *call_med,
 
1181
                              pjsua_med_tp_st tp_st)
 
1182
{
 
1183
    if (pjsua_var.ua_cfg.cb.on_call_media_transport_state &&
 
1184
        call_med->tp_st != tp_st)
 
1185
    {
 
1186
        pjsua_med_tp_state_info info;
 
1187
 
 
1188
        pj_bzero(&info, sizeof(info));
 
1189
        info.med_idx = call_med->idx;
 
1190
        info.state = tp_st;
 
1191
        info.status = call_med->tp_ready;
 
1192
        (*pjsua_var.ua_cfg.cb.on_call_media_transport_state)(
 
1193
            call_med->call->index, &info);
 
1194
    }
 
1195
 
 
1196
    call_med->tp_st = tp_st;
 
1197
}
 
1198
 
 
1199
/* Callback to resume pjsua_call_media_init() after media transport
 
1200
 * creation is completed.
 
1201
 */
 
1202
static pj_status_t call_media_init_cb(pjsua_call_media *call_med,
 
1203
                                      pj_status_t status,
 
1204
                                      int security_level,
 
1205
                                      int *sip_err_code)
 
1206
{
 
1207
    pjsua_acc *acc = &pjsua_var.acc[call_med->call->acc_id];
 
1208
    pjmedia_transport_info tpinfo;
 
1209
    int err_code = 0;
 
1210
 
 
1211
    if (status != PJ_SUCCESS)
 
1212
        goto on_return;
 
1213
 
 
1214
    pjmedia_transport_simulate_lost(call_med->tp, PJMEDIA_DIR_ENCODING,
 
1215
                                    pjsua_var.media_cfg.tx_drop_pct);
 
1216
 
 
1217
    pjmedia_transport_simulate_lost(call_med->tp, PJMEDIA_DIR_DECODING,
 
1218
                                    pjsua_var.media_cfg.rx_drop_pct);
 
1219
 
 
1220
    if (call_med->tp_st == PJSUA_MED_TP_CREATING)
 
1221
        pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_IDLE);
 
1222
 
 
1223
    if (!call_med->tp_orig &&
 
1224
        pjsua_var.ua_cfg.cb.on_create_media_transport)
 
1225
    {
 
1226
        call_med->use_custom_med_tp = PJ_TRUE;
 
1227
    } else
 
1228
        call_med->use_custom_med_tp = PJ_FALSE;
 
1229
 
 
1230
#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
 
1231
    /* This function may be called when SRTP transport already exists
 
1232
     * (e.g: in re-invite, update), don't need to destroy/re-create.
 
1233
     */
 
1234
    if (!call_med->tp_orig) {
 
1235
        pjmedia_srtp_setting srtp_opt;
 
1236
        pjmedia_transport *srtp = NULL;
 
1237
 
 
1238
        /* Check if SRTP requires secure signaling */
 
1239
        if (acc->cfg.use_srtp != PJMEDIA_SRTP_DISABLED) {
 
1240
            if (security_level < acc->cfg.srtp_secure_signaling) {
 
1241
                err_code = PJSIP_SC_NOT_ACCEPTABLE;
 
1242
                status = PJSIP_ESESSIONINSECURE;
 
1243
                goto on_return;
 
1244
            }
 
1245
        }
 
1246
 
 
1247
        /* Always create SRTP adapter */
 
1248
        pjmedia_srtp_setting_default(&srtp_opt);
 
1249
        srtp_opt.close_member_tp = PJ_TRUE;
 
1250
 
 
1251
        /* If media session has been ever established, let's use remote's 
 
1252
         * preference in SRTP usage policy, especially when it is stricter.
 
1253
         */
 
1254
        if (call_med->rem_srtp_use > acc->cfg.use_srtp)
 
1255
            srtp_opt.use = call_med->rem_srtp_use;
 
1256
        else
 
1257
            srtp_opt.use = acc->cfg.use_srtp;
 
1258
 
 
1259
        status = pjmedia_transport_srtp_create(pjsua_var.med_endpt,
 
1260
                                               call_med->tp,
 
1261
                                               &srtp_opt, &srtp);
 
1262
        if (status != PJ_SUCCESS) {
 
1263
            err_code = PJSIP_SC_INTERNAL_SERVER_ERROR;
 
1264
            goto on_return;
 
1265
        }
 
1266
 
 
1267
        /* Set SRTP as current media transport */
 
1268
        call_med->tp_orig = call_med->tp;
 
1269
        call_med->tp = srtp;
 
1270
    }
 
1271
#else
 
1272
    call_med->tp_orig = call_med->tp;
 
1273
    PJ_UNUSED_ARG(security_level);
 
1274
#endif
 
1275
 
 
1276
 
 
1277
    pjmedia_transport_info_init(&tpinfo);
 
1278
    pjmedia_transport_get_info(call_med->tp, &tpinfo);
 
1279
 
 
1280
    pj_sockaddr_cp(&call_med->rtp_addr, &tpinfo.sock_info.rtp_addr_name);
 
1281
 
 
1282
 
 
1283
on_return:
 
1284
    if (status != PJ_SUCCESS && call_med->tp) {
 
1285
        pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_NULL);
 
1286
        pjmedia_transport_close(call_med->tp);
 
1287
        call_med->tp = NULL;
 
1288
    }
 
1289
 
 
1290
    if (sip_err_code)
 
1291
        *sip_err_code = err_code;
 
1292
 
 
1293
    if (call_med->med_init_cb) {
 
1294
        pjsua_med_tp_state_info info;
 
1295
 
 
1296
        pj_bzero(&info, sizeof(info));
 
1297
        info.status = status;
 
1298
        info.state = call_med->tp_st;
 
1299
        info.med_idx = call_med->idx;
 
1300
        info.sip_err_code = err_code;
 
1301
        (*call_med->med_init_cb)(call_med->call->index, &info);
 
1302
    }
 
1303
 
 
1304
    return status;
 
1305
}
 
1306
 
 
1307
/* Determine if call's media is being changed, for example when video is being
 
1308
 * added. Then we can reject incoming re-INVITE, for example. This is the
 
1309
 * solution for https://trac.pjsip.org/repos/ticket/1738
 
1310
 */
 
1311
pj_bool_t  pjsua_call_media_is_changing(pjsua_call *call)
 
1312
{
 
1313
    /* The problem in #1738 occurs because we do handle_events() loop while
 
1314
     * adding media, which could cause incoming re-INVITE to be processed and
 
1315
     * cause havoc. Since the handle_events() loop only happens while adding
 
1316
     * media, it is sufficient to only check if "prov > cnt" for now.
 
1317
     */
 
1318
    return call->med_prov_cnt > call->med_cnt;
 
1319
}
 
1320
 
 
1321
/* Initialize the media line */
 
1322
pj_status_t pjsua_call_media_init(pjsua_call_media *call_med,
 
1323
                                  pjmedia_type type,
 
1324
                                  const pjsua_transport_config *tcfg,
 
1325
                                  int security_level,
 
1326
                                  int *sip_err_code,
 
1327
                                  pj_bool_t async,
 
1328
                                  pjsua_med_tp_state_cb cb)
 
1329
{
 
1330
    pj_status_t status = PJ_SUCCESS;
 
1331
 
 
1332
    /*
 
1333
     * Note: this function may be called when the media already exists
 
1334
     * (e.g. in reinvites, updates, etc.)
 
1335
     */
 
1336
    call_med->type = type;
 
1337
 
 
1338
    /* Create the media transport for initial call. Here are the possible
 
1339
     * media transport state and the action needed:
 
1340
     * - PJSUA_MED_TP_NULL or call_med->tp==NULL, create one.
 
1341
     * - PJSUA_MED_TP_RUNNING, do nothing.
 
1342
     * - PJSUA_MED_TP_DISABLED, re-init (media_create(), etc). Currently,
 
1343
     *   this won't happen as media_channel_update() will always clean up
 
1344
     *   the unused transport of a disabled media.
 
1345
     */
 
1346
    if (call_med->tp == NULL) {
 
1347
#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
 
1348
        /* While in initial call, set default video devices */
 
1349
        if (type == PJMEDIA_TYPE_VIDEO) {
 
1350
            status = pjsua_vid_channel_init(call_med);
 
1351
            if (status != PJ_SUCCESS)
 
1352
                return status;
 
1353
        }
 
1354
#endif
 
1355
 
 
1356
        pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_CREATING);
 
1357
 
 
1358
        if (pjsua_var.acc[call_med->call->acc_id].cfg.ice_cfg.enable_ice) {
 
1359
            status = create_ice_media_transport(tcfg, call_med, async);
 
1360
            if (async && status == PJ_EPENDING) {
 
1361
                /* We will resume call media initialization in the
 
1362
                 * on_ice_complete() callback.
 
1363
                 */
 
1364
                call_med->med_create_cb = &call_media_init_cb;
 
1365
                call_med->med_init_cb = cb;
 
1366
                
 
1367
                return PJ_EPENDING;
 
1368
            }
 
1369
        } else {
 
1370
            status = create_udp_media_transport(tcfg, call_med);
 
1371
        }
 
1372
 
 
1373
        if (status != PJ_SUCCESS) {
 
1374
            PJ_PERROR(1,(THIS_FILE, status, "Error creating media transport"));
 
1375
            return status;
 
1376
        }
 
1377
 
 
1378
        /* Media transport creation completed immediately, so 
 
1379
         * we don't need to call the callback.
 
1380
         */
 
1381
        call_med->med_init_cb = NULL;
 
1382
 
 
1383
    } else if (call_med->tp_st == PJSUA_MED_TP_DISABLED) {
 
1384
        /* Media is being reenabled. */
 
1385
        //pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_IDLE);
 
1386
 
 
1387
        pj_assert(!"Currently no media transport reuse");
 
1388
    }
 
1389
 
 
1390
    return call_media_init_cb(call_med, status, security_level,
 
1391
                              sip_err_code);
 
1392
}
 
1393
 
 
1394
/* Callback to resume pjsua_media_channel_init() after media transport
 
1395
 * initialization is completed.
 
1396
 */
 
1397
static pj_status_t media_channel_init_cb(pjsua_call_id call_id,
 
1398
                                         const pjsua_med_tp_state_info *info)
 
1399
{
 
1400
    pjsua_call *call = &pjsua_var.calls[call_id];
 
1401
    pj_status_t status = (info? info->status : PJ_SUCCESS);
 
1402
    unsigned mi;
 
1403
 
 
1404
    if (info) {
 
1405
        pj_mutex_lock(call->med_ch_mutex);
 
1406
 
 
1407
        /* Set the callback to NULL to indicate that the async operation
 
1408
         * has completed.
 
1409
         */
 
1410
        call->media_prov[info->med_idx].med_init_cb = NULL;
 
1411
 
 
1412
        /* In case of failure, save the information to be returned
 
1413
         * by the last media transport to finish.
 
1414
         */
 
1415
        if (info->status != PJ_SUCCESS)
 
1416
            pj_memcpy(&call->med_ch_info, info, sizeof(*info));
 
1417
 
 
1418
        /* Check whether all the call's medias have finished calling their
 
1419
         * callbacks.
 
1420
         */
 
1421
        for (mi=0; mi < call->med_prov_cnt; ++mi) {
 
1422
            pjsua_call_media *call_med = &call->media_prov[mi];
 
1423
 
 
1424
            if (call_med->med_init_cb) {
 
1425
                pj_mutex_unlock(call->med_ch_mutex);
 
1426
                return PJ_SUCCESS;
 
1427
            }
 
1428
 
 
1429
            if (call_med->tp_ready != PJ_SUCCESS)
 
1430
                status = call_med->tp_ready;
 
1431
        }
 
1432
 
 
1433
        /* OK, we are called by the last media transport finished. */
 
1434
        pj_mutex_unlock(call->med_ch_mutex);
 
1435
    }
 
1436
 
 
1437
    if (call->med_ch_mutex) {
 
1438
        pj_mutex_destroy(call->med_ch_mutex);
 
1439
        call->med_ch_mutex = NULL;
 
1440
    }
 
1441
 
 
1442
    if (status != PJ_SUCCESS) {
 
1443
        if (call->med_ch_info.status == PJ_SUCCESS) {
 
1444
            call->med_ch_info.status = status;
 
1445
            call->med_ch_info.sip_err_code = PJSIP_SC_TEMPORARILY_UNAVAILABLE;
 
1446
        }
 
1447
        pjsua_media_prov_clean_up(call_id);
 
1448
        goto on_return;
 
1449
    }
 
1450
 
 
1451
    /* Tell the media transport of a new offer/answer session */
 
1452
    for (mi=0; mi < call->med_prov_cnt; ++mi) {
 
1453
        pjsua_call_media *call_med = &call->media_prov[mi];
 
1454
 
 
1455
        /* Note: tp may be NULL if this media line is disabled */
 
1456
        if (call_med->tp && call_med->tp_st == PJSUA_MED_TP_IDLE) {
 
1457
            pj_pool_t *tmp_pool = call->async_call.pool_prov;
 
1458
            
 
1459
            if (!tmp_pool) {
 
1460
                tmp_pool = (call->inv? call->inv->pool_prov:
 
1461
                            call->async_call.dlg->pool);
 
1462
            }
 
1463
 
 
1464
            if (call_med->use_custom_med_tp) {
 
1465
                unsigned custom_med_tp_flags = PJSUA_MED_TP_CLOSE_MEMBER;
 
1466
 
 
1467
                /* Use custom media transport returned by the application */
 
1468
                call_med->tp =
 
1469
                    (*pjsua_var.ua_cfg.cb.on_create_media_transport)
 
1470
                        (call_id, mi, call_med->tp,
 
1471
                         custom_med_tp_flags);
 
1472
                if (!call_med->tp) {
 
1473
                    status =
 
1474
                        PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_TEMPORARILY_UNAVAILABLE);
 
1475
                }
 
1476
            }
 
1477
 
 
1478
            if (call_med->tp) {
 
1479
                status = pjmedia_transport_media_create(
 
1480
                             call_med->tp, tmp_pool,
 
1481
                             0, call->async_call.rem_sdp, mi);
 
1482
            }
 
1483
            if (status != PJ_SUCCESS) {
 
1484
                call->med_ch_info.status = status;
 
1485
                call->med_ch_info.med_idx = mi;
 
1486
                call->med_ch_info.state = call_med->tp_st;
 
1487
                call->med_ch_info.sip_err_code = PJSIP_SC_TEMPORARILY_UNAVAILABLE;
 
1488
                pjsua_media_prov_clean_up(call_id);
 
1489
                goto on_return;
 
1490
            }
 
1491
 
 
1492
            pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_INIT);
 
1493
        }
 
1494
    }
 
1495
 
 
1496
    call->med_ch_info.status = PJ_SUCCESS;
 
1497
 
 
1498
on_return:
 
1499
    if (call->med_ch_cb)
 
1500
        (*call->med_ch_cb)(call->index, &call->med_ch_info);
 
1501
 
 
1502
    return status;
 
1503
}
 
1504
 
 
1505
 
 
1506
/* Clean up media transports in provisional media that is not used
 
1507
 * by call media.
 
1508
 */
 
1509
static void media_prov_clean_up(pjsua_call_id call_id, int idx)
 
1510
{
 
1511
    pjsua_call *call = &pjsua_var.calls[call_id];
 
1512
    unsigned i;
 
1513
 
 
1514
    for (i = idx; i < call->med_prov_cnt; ++i) {
 
1515
        pjsua_call_media *call_med = &call->media_prov[i];
 
1516
        unsigned j;
 
1517
        pj_bool_t used = PJ_FALSE;
 
1518
 
 
1519
        if (call_med->tp == NULL)
 
1520
            continue;
 
1521
 
 
1522
        for (j = 0; j < call->med_cnt; ++j) {
 
1523
            if (call->media[j].tp == call_med->tp) {
 
1524
                used = PJ_TRUE;
 
1525
                break;
 
1526
            }
 
1527
        }
 
1528
 
 
1529
        if (!used) {
 
1530
            if (call_med->tp_st > PJSUA_MED_TP_IDLE) {
 
1531
                pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_IDLE);
 
1532
                pjmedia_transport_media_stop(call_med->tp);
 
1533
            }
 
1534
            pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_NULL);
 
1535
            pjmedia_transport_close(call_med->tp);
 
1536
            call_med->tp = call_med->tp_orig = NULL;
 
1537
        }
 
1538
    }
 
1539
}
 
1540
 
 
1541
void pjsua_media_prov_clean_up(pjsua_call_id call_id)
 
1542
{
 
1543
    media_prov_clean_up(call_id, 0);
 
1544
}
 
1545
 
 
1546
 
 
1547
pj_status_t pjsua_media_channel_init(pjsua_call_id call_id,
 
1548
                                     pjsip_role_e role,
 
1549
                                     int security_level,
 
1550
                                     pj_pool_t *tmp_pool,
 
1551
                                     const pjmedia_sdp_session *rem_sdp,
 
1552
                                     int *sip_err_code,
 
1553
                                     pj_bool_t async,
 
1554
                                     pjsua_med_tp_state_cb cb)
 
1555
{
 
1556
    const pj_str_t STR_AUDIO = { "audio", 5 };
 
1557
    const pj_str_t STR_VIDEO = { "video", 5 };
 
1558
    pjsua_call *call = &pjsua_var.calls[call_id];
 
1559
    pjsua_acc *acc = &pjsua_var.acc[call->acc_id];
 
1560
    pj_uint8_t maudidx[PJSUA_MAX_CALL_MEDIA];
 
1561
    unsigned maudcnt = PJ_ARRAY_SIZE(maudidx);
 
1562
    unsigned mtotaudcnt = PJ_ARRAY_SIZE(maudidx);
 
1563
    pj_uint8_t mvididx[PJSUA_MAX_CALL_MEDIA];
 
1564
    unsigned mvidcnt = PJ_ARRAY_SIZE(mvididx);
 
1565
    unsigned mtotvidcnt = PJ_ARRAY_SIZE(mvididx);
 
1566
    unsigned mi;
 
1567
    pj_bool_t pending_med_tp = PJ_FALSE;
 
1568
    pj_bool_t reinit = PJ_FALSE;
 
1569
    pj_status_t status;
 
1570
 
 
1571
    PJ_UNUSED_ARG(role);
 
1572
 
 
1573
    /*
 
1574
     * Note: this function may be called when the media already exists
 
1575
     * (e.g. in reinvites, updates, etc).
 
1576
     */
 
1577
 
 
1578
    if (pjsua_get_state() != PJSUA_STATE_RUNNING) {
 
1579
        if (sip_err_code) *sip_err_code = PJSIP_SC_SERVICE_UNAVAILABLE;
 
1580
        return PJ_EBUSY;
 
1581
    }
 
1582
 
 
1583
    if (async) {
 
1584
        pj_pool_t *tmppool = (call->inv? call->inv->pool_prov:
 
1585
                              call->async_call.dlg->pool);
 
1586
 
 
1587
        status = pj_mutex_create_simple(tmppool, NULL, &call->med_ch_mutex);
 
1588
        if (status != PJ_SUCCESS)
 
1589
            return status;
 
1590
    }
 
1591
 
 
1592
    if (call->inv && call->inv->state == PJSIP_INV_STATE_CONFIRMED)
 
1593
        reinit = PJ_TRUE;
 
1594
 
 
1595
    PJ_LOG(4,(THIS_FILE, "Call %d: %sinitializing media..",
 
1596
                         call_id, (reinit?"re-":"") ));
 
1597
 
 
1598
    pj_log_push_indent();
 
1599
 
 
1600
    /* Init provisional media state */
 
1601
    if (call->med_cnt == 0) {
 
1602
        /* New media session, just copy whole from call media state. */
 
1603
        pj_memcpy(call->media_prov, call->media, sizeof(call->media));
 
1604
    } else {
 
1605
        /* Clean up any unused transports. Note that when local SDP reoffer
 
1606
         * is rejected by remote, there may be any initialized transports that
 
1607
         * are not used by call media and currently there is no notification
 
1608
         * from PJSIP level regarding the reoffer rejection.
 
1609
         */
 
1610
        pjsua_media_prov_clean_up(call_id);
 
1611
 
 
1612
        /* Updating media session, copy from call media state. */
 
1613
        pj_memcpy(call->media_prov, call->media,
 
1614
                  sizeof(call->media[0]) * call->med_cnt);
 
1615
    }
 
1616
    call->med_prov_cnt = call->med_cnt;
 
1617
 
 
1618
#if DISABLED_FOR_TICKET_1185
 
1619
    /* Return error if media transport has not been created yet
 
1620
     * (e.g. application is starting)
 
1621
     */
 
1622
    for (i=0; i<call->med_cnt; ++i) {
 
1623
        if (call->media[i].tp == NULL) {
 
1624
            status = PJ_EBUSY;
 
1625
            goto on_error;
 
1626
        }
 
1627
    }
 
1628
#endif
 
1629
 
 
1630
    /* Get media count for each media type */
 
1631
    if (rem_sdp) {
 
1632
        sort_media(rem_sdp, &STR_AUDIO, acc->cfg.use_srtp,
 
1633
                   maudidx, &maudcnt, &mtotaudcnt);
 
1634
        if (maudcnt==0) {
 
1635
            /* Expecting audio in the offer */
 
1636
            if (sip_err_code) *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE_HERE;
 
1637
            status = PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_NOT_ACCEPTABLE_HERE);
 
1638
            goto on_error;
 
1639
        }
 
1640
 
 
1641
#if PJMEDIA_HAS_VIDEO
 
1642
        sort_media(rem_sdp, &STR_VIDEO, acc->cfg.use_srtp,
 
1643
                   mvididx, &mvidcnt, &mtotvidcnt);
 
1644
#else
 
1645
        mvidcnt = mtotvidcnt = 0;
 
1646
        PJ_UNUSED_ARG(STR_VIDEO);
 
1647
#endif
 
1648
 
 
1649
        /* Update media count only when remote add any media, this media count
 
1650
         * must never decrease. Also note that we shouldn't apply the media
 
1651
         * count setting (of the call setting) before the SDP negotiation.
 
1652
         */
 
1653
        if (call->med_prov_cnt < rem_sdp->media_count)
 
1654
            call->med_prov_cnt = PJ_MIN(rem_sdp->media_count,
 
1655
                                        PJSUA_MAX_CALL_MEDIA);
 
1656
 
 
1657
        call->rem_offerer = PJ_TRUE;
 
1658
        call->rem_aud_cnt = maudcnt;
 
1659
        call->rem_vid_cnt = mvidcnt;
 
1660
 
 
1661
    } else {
 
1662
 
 
1663
        /* If call already established, calculate media count from current 
 
1664
         * local active SDP and call setting. Otherwise, calculate media
 
1665
         * count from the call setting only.
 
1666
         */
 
1667
        if (reinit) {
 
1668
            const pjmedia_sdp_session *sdp;
 
1669
 
 
1670
            status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &sdp);
 
1671
            pj_assert(status == PJ_SUCCESS);
 
1672
 
 
1673
            sort_media(sdp, &STR_AUDIO, acc->cfg.use_srtp,
 
1674
                       maudidx, &maudcnt, &mtotaudcnt);
 
1675
            pj_assert(maudcnt > 0);
 
1676
 
 
1677
            sort_media(sdp, &STR_VIDEO, acc->cfg.use_srtp,
 
1678
                       mvididx, &mvidcnt, &mtotvidcnt);
 
1679
 
 
1680
            /* Call setting may add or remove media. Adding media is done by
 
1681
             * enabling any disabled/port-zeroed media first, then adding new
 
1682
             * media whenever needed. Removing media is done by disabling
 
1683
             * media with the lowest 'quality'.
 
1684
             */
 
1685
 
 
1686
            /* Check if we need to add new audio */
 
1687
            if (maudcnt < call->opt.aud_cnt &&
 
1688
                mtotaudcnt < call->opt.aud_cnt)
 
1689
            {
 
1690
                for (mi = 0; mi < call->opt.aud_cnt - mtotaudcnt; ++mi)
 
1691
                    maudidx[maudcnt++] = (pj_uint8_t)call->med_prov_cnt++;
 
1692
                
 
1693
                mtotaudcnt = call->opt.aud_cnt;
 
1694
            }
 
1695
            maudcnt = call->opt.aud_cnt;
 
1696
 
 
1697
            /* Check if we need to add new video */
 
1698
            if (mvidcnt < call->opt.vid_cnt &&
 
1699
                mtotvidcnt < call->opt.vid_cnt)
 
1700
            {
 
1701
                for (mi = 0; mi < call->opt.vid_cnt - mtotvidcnt; ++mi)
 
1702
                    mvididx[mvidcnt++] = (pj_uint8_t)call->med_prov_cnt++;
 
1703
 
 
1704
                mtotvidcnt = call->opt.vid_cnt;
 
1705
            }
 
1706
            mvidcnt = call->opt.vid_cnt;
 
1707
 
 
1708
        } else {
 
1709
 
 
1710
            maudcnt = mtotaudcnt = call->opt.aud_cnt;
 
1711
            for (mi=0; mi<maudcnt; ++mi) {
 
1712
                maudidx[mi] = (pj_uint8_t)mi;
 
1713
            }
 
1714
            mvidcnt = mtotvidcnt = call->opt.vid_cnt;
 
1715
            for (mi=0; mi<mvidcnt; ++mi) {
 
1716
                mvididx[mi] = (pj_uint8_t)(maudcnt + mi);
 
1717
            }
 
1718
            call->med_prov_cnt = maudcnt + mvidcnt;
 
1719
 
 
1720
            /* Need to publish supported media? */
 
1721
            if (call->opt.flag & PJSUA_CALL_INCLUDE_DISABLED_MEDIA) {
 
1722
                if (mtotaudcnt == 0) {
 
1723
                    mtotaudcnt = 1;
 
1724
                    maudidx[0] = (pj_uint8_t)call->med_prov_cnt++;
 
1725
                }
 
1726
#if PJMEDIA_HAS_VIDEO
 
1727
                if (mtotvidcnt == 0) {
 
1728
                    mtotvidcnt = 1;
 
1729
                    mvididx[0] = (pj_uint8_t)call->med_prov_cnt++;
 
1730
                }
 
1731
#endif
 
1732
            }
 
1733
        }
 
1734
 
 
1735
        call->rem_offerer = PJ_FALSE;
 
1736
    }
 
1737
 
 
1738
    if (call->med_prov_cnt == 0) {
 
1739
        /* Expecting at least one media */
 
1740
        if (sip_err_code) *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE_HERE;
 
1741
        status = PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_NOT_ACCEPTABLE_HERE);
 
1742
        goto on_error;
 
1743
    }
 
1744
 
 
1745
    if (async) {
 
1746
        call->med_ch_cb = cb;
 
1747
    }
 
1748
 
 
1749
    if (rem_sdp) {
 
1750
        call->async_call.rem_sdp =
 
1751
            pjmedia_sdp_session_clone(call->inv->pool_prov, rem_sdp);
 
1752
    } else {
 
1753
        call->async_call.rem_sdp = NULL;
 
1754
    }
 
1755
 
 
1756
    call->async_call.pool_prov = tmp_pool;
 
1757
 
 
1758
    /* Initialize each media line */
 
1759
    for (mi=0; mi < call->med_prov_cnt; ++mi) {
 
1760
        pjsua_call_media *call_med = &call->media_prov[mi];
 
1761
        pj_bool_t enabled = PJ_FALSE;
 
1762
        pjmedia_type media_type = PJMEDIA_TYPE_UNKNOWN;
 
1763
 
 
1764
        if (pj_memchr(maudidx, mi, mtotaudcnt * sizeof(maudidx[0]))) {
 
1765
            media_type = PJMEDIA_TYPE_AUDIO;
 
1766
            if (call->opt.aud_cnt &&
 
1767
                pj_memchr(maudidx, mi, maudcnt * sizeof(maudidx[0])))
 
1768
            {
 
1769
                enabled = PJ_TRUE;
 
1770
            }
 
1771
        } else if (pj_memchr(mvididx, mi, mtotvidcnt * sizeof(mvididx[0]))) {
 
1772
            media_type = PJMEDIA_TYPE_VIDEO;
 
1773
            if (call->opt.vid_cnt &&
 
1774
                pj_memchr(mvididx, mi, mvidcnt * sizeof(mvididx[0])))
 
1775
            {
 
1776
                enabled = PJ_TRUE;
 
1777
            }
 
1778
        }
 
1779
 
 
1780
        if (enabled) {
 
1781
            status = pjsua_call_media_init(call_med, media_type,
 
1782
                                           &acc->cfg.rtp_cfg,
 
1783
                                           security_level, sip_err_code,
 
1784
                                           async,
 
1785
                                           (async? &media_channel_init_cb:
 
1786
                                            NULL));
 
1787
            if (status == PJ_EPENDING) {
 
1788
                pending_med_tp = PJ_TRUE;
 
1789
            } else if (status != PJ_SUCCESS) {
 
1790
                if (pending_med_tp) {
 
1791
                    /* Save failure information. */
 
1792
                    call_med->tp_ready = status;
 
1793
                    pj_bzero(&call->med_ch_info, sizeof(call->med_ch_info));
 
1794
                    call->med_ch_info.status = status;
 
1795
                    call->med_ch_info.state = call_med->tp_st;
 
1796
                    call->med_ch_info.med_idx = call_med->idx;
 
1797
                    if (sip_err_code)
 
1798
                        call->med_ch_info.sip_err_code = *sip_err_code;
 
1799
 
 
1800
                    /* We will return failure in the callback later. */
 
1801
                    return PJ_EPENDING;
 
1802
                }
 
1803
 
 
1804
                pjsua_media_prov_clean_up(call_id);
 
1805
                goto on_error;
 
1806
            }
 
1807
        } else {
 
1808
            /* By convention, the media is disabled if transport is NULL 
 
1809
             * or transport state is PJSUA_MED_TP_DISABLED.
 
1810
             */
 
1811
            if (call_med->tp) {
 
1812
                // Don't close transport here, as SDP negotiation has not been
 
1813
                // done and stream may be still active. Once SDP negotiation
 
1814
                // is done (channel_update() invoked), this transport will be
 
1815
                // closed there.
 
1816
                //pjmedia_transport_close(call_med->tp);
 
1817
                //call_med->tp = NULL;
 
1818
                pj_assert(call_med->tp_st == PJSUA_MED_TP_INIT || 
 
1819
                          call_med->tp_st == PJSUA_MED_TP_RUNNING);
 
1820
                pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_DISABLED);
 
1821
            }
 
1822
 
 
1823
            /* Put media type just for info */
 
1824
            call_med->type = media_type;
 
1825
        }
 
1826
    }
 
1827
 
 
1828
    call->audio_idx = maudidx[0];
 
1829
 
 
1830
    PJ_LOG(4,(THIS_FILE, "Media index %d selected for audio call %d",
 
1831
              call->audio_idx, call->index));
 
1832
 
 
1833
    if (pending_med_tp) {
 
1834
        /* We shouldn't use temporary pool anymore. */
 
1835
        call->async_call.pool_prov = NULL;
 
1836
        /* We have a pending media transport initialization. */
 
1837
        pj_log_pop_indent();
 
1838
        return PJ_EPENDING;
 
1839
    }
 
1840
 
 
1841
    /* Media transport initialization completed immediately, so 
 
1842
     * we don't need to call the callback.
 
1843
     */
 
1844
    call->med_ch_cb = NULL;
 
1845
 
 
1846
    status = media_channel_init_cb(call_id, NULL);
 
1847
    if (status != PJ_SUCCESS && sip_err_code)
 
1848
        *sip_err_code = call->med_ch_info.sip_err_code;
 
1849
 
 
1850
    pj_log_pop_indent();
 
1851
    return status;
 
1852
 
 
1853
on_error:
 
1854
    if (call->med_ch_mutex) {
 
1855
        pj_mutex_destroy(call->med_ch_mutex);
 
1856
        call->med_ch_mutex = NULL;
 
1857
    }
 
1858
 
 
1859
    pj_log_pop_indent();
 
1860
    return status;
 
1861
}
 
1862
 
 
1863
 
 
1864
/* Create SDP based on the current media channel. Note that, this function
 
1865
 * will not modify the media channel, so when receiving new offer or
 
1866
 * updating media count (via call setting), media channel must be reinit'd
 
1867
 * (using pjsua_media_channel_init()) first before calling this function.
 
1868
 */
 
1869
pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id, 
 
1870
                                           pj_pool_t *pool,
 
1871
                                           const pjmedia_sdp_session *rem_sdp,
 
1872
                                           pjmedia_sdp_session **p_sdp,
 
1873
                                           int *sip_err_code)
 
1874
{
 
1875
    enum { MAX_MEDIA = PJSUA_MAX_CALL_MEDIA };
 
1876
    pjmedia_sdp_session *sdp;
 
1877
    pj_sockaddr origin;
 
1878
    pjsua_call *call = &pjsua_var.calls[call_id];
 
1879
    pjmedia_sdp_neg_state sdp_neg_state = PJMEDIA_SDP_NEG_STATE_NULL;
 
1880
    unsigned mi;
 
1881
    unsigned tot_bandw_tias = 0;
 
1882
    pj_status_t status;
 
1883
 
 
1884
    if (pjsua_get_state() != PJSUA_STATE_RUNNING)
 
1885
        return PJ_EBUSY;
 
1886
 
 
1887
#if 0
 
1888
    // This function should not really change the media channel.
 
1889
    if (rem_sdp) {
 
1890
        /* If this is a re-offer, let's re-initialize media as remote may
 
1891
         * add or remove media
 
1892
         */
 
1893
        if (call->inv && call->inv->state == PJSIP_INV_STATE_CONFIRMED) {
 
1894
            status = pjsua_media_channel_init(call_id, PJSIP_ROLE_UAS,
 
1895
                                              call->secure_level, pool,
 
1896
                                              rem_sdp, sip_err_code,
 
1897
                                              PJ_FALSE, NULL);
 
1898
            if (status != PJ_SUCCESS)
 
1899
                return status;
 
1900
        }
 
1901
    } else {
 
1902
        /* Audio is first in our offer, by convention */
 
1903
        // The audio_idx should not be changed here, as this function may be
 
1904
        // called in generating re-offer and the current active audio index
 
1905
        // can be anywhere.
 
1906
        //call->audio_idx = 0;
 
1907
    }
 
1908
#endif
 
1909
 
 
1910
#if 0
 
1911
    // Since r3512, old-style hold should have got transport, created by 
 
1912
    // pjsua_media_channel_init() in initial offer/answer or remote reoffer.
 
1913
    /* Create media if it's not created. This could happen when call is
 
1914
     * currently on-hold (with the old style hold)
 
1915
     */
 
1916
    if (call->media[call->audio_idx].tp == NULL) {
 
1917
        pjsip_role_e role;
 
1918
        role = (rem_sdp ? PJSIP_ROLE_UAS : PJSIP_ROLE_UAC);
 
1919
        status = pjsua_media_channel_init(call_id, role, call->secure_level, 
 
1920
                                          pool, rem_sdp, sip_err_code);
 
1921
        if (status != PJ_SUCCESS)
 
1922
            return status;
 
1923
    }
 
1924
#endif
 
1925
 
 
1926
    /* Get SDP negotiator state */
 
1927
    if (call->inv && call->inv->neg)
 
1928
        sdp_neg_state = pjmedia_sdp_neg_get_state(call->inv->neg);
 
1929
 
 
1930
    /* Get one address to use in the origin field */
 
1931
    pj_bzero(&origin, sizeof(origin));
 
1932
    for (mi=0; mi<call->med_prov_cnt; ++mi) {
 
1933
        pjmedia_transport_info tpinfo;
 
1934
 
 
1935
        if (call->media_prov[mi].tp == NULL)
 
1936
            continue;
 
1937
 
 
1938
        pjmedia_transport_info_init(&tpinfo);
 
1939
        pjmedia_transport_get_info(call->media_prov[mi].tp, &tpinfo);
 
1940
        pj_sockaddr_cp(&origin, &tpinfo.sock_info.rtp_addr_name);
 
1941
        break;
 
1942
    }
 
1943
 
 
1944
    /* Create the base (blank) SDP */
 
1945
    status = pjmedia_endpt_create_base_sdp(pjsua_var.med_endpt, pool, NULL,
 
1946
                                           &origin, &sdp);
 
1947
    if (status != PJ_SUCCESS)
 
1948
        return status;
 
1949
 
 
1950
    /* Process each media line */
 
1951
    for (mi=0; mi<call->med_prov_cnt; ++mi) {
 
1952
        pjsua_call_media *call_med = &call->media_prov[mi];
 
1953
        pjmedia_sdp_media *m = NULL;
 
1954
        pjmedia_transport_info tpinfo;
 
1955
        unsigned i;
 
1956
 
 
1957
        if (rem_sdp && mi >= rem_sdp->media_count) {
 
1958
            /* Remote might have removed some media lines. */
 
1959
            media_prov_clean_up(call->index, rem_sdp->media_count);
 
1960
            call->med_prov_cnt = rem_sdp->media_count;
 
1961
            break;
 
1962
        }
 
1963
 
 
1964
        if (call_med->tp == NULL || call_med->tp_st == PJSUA_MED_TP_DISABLED)
 
1965
        {
 
1966
            /*
 
1967
             * This media is disabled. Just create a valid SDP with zero
 
1968
             * port.
 
1969
             */
 
1970
            if (rem_sdp) {
 
1971
                /* Just clone the remote media and deactivate it */
 
1972
                m = pjmedia_sdp_media_clone_deactivate(pool,
 
1973
                                                       rem_sdp->media[mi]);
 
1974
            } else {
 
1975
                m = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_media);
 
1976
                m->desc.transport = pj_str("RTP/AVP");
 
1977
                m->desc.fmt_count = 1;
 
1978
 
 
1979
                switch (call_med->type) {
 
1980
                case PJMEDIA_TYPE_AUDIO:
 
1981
                    m->desc.media = pj_str("audio");
 
1982
                    m->desc.fmt[0] = pj_str("0");
 
1983
                    break;
 
1984
                case PJMEDIA_TYPE_VIDEO:
 
1985
                    m->desc.media = pj_str("video");
 
1986
                    m->desc.fmt[0] = pj_str("31");
 
1987
                    break;
 
1988
                default:
 
1989
                    /* This must be us generating re-offer, and some unknown
 
1990
                     * media may exist, so just clone from active local SDP
 
1991
                     * (and it should have been deactivated already).
 
1992
                     */
 
1993
                    pj_assert(call->inv && call->inv->neg &&
 
1994
                              sdp_neg_state == PJMEDIA_SDP_NEG_STATE_DONE);
 
1995
                    {
 
1996
                        const pjmedia_sdp_session *s_;
 
1997
                        pjmedia_sdp_neg_get_active_local(call->inv->neg, &s_);
 
1998
 
 
1999
                        pj_assert(mi < s_->media_count);
 
2000
                        m = pjmedia_sdp_media_clone(pool, s_->media[mi]);
 
2001
                        m->desc.port = 0;
 
2002
                    }
 
2003
                    break;
 
2004
                }
 
2005
            }
 
2006
 
 
2007
            /* Add connection line, if none */
 
2008
            if (m->conn == NULL && sdp->conn == NULL) {
 
2009
                pj_bool_t use_ipv6;
 
2010
 
 
2011
                use_ipv6 = (pjsua_var.acc[call->acc_id].cfg.ipv6_media_use !=
 
2012
                            PJSUA_IPV6_DISABLED);
 
2013
 
 
2014
                m->conn = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_conn);
 
2015
                m->conn->net_type = pj_str("IN");
 
2016
                if (use_ipv6) {
 
2017
                    m->conn->addr_type = pj_str("IP6");
 
2018
                    m->conn->addr = pj_str("::1");
 
2019
                } else {
 
2020
                    m->conn->addr_type = pj_str("IP4");
 
2021
                    m->conn->addr = pj_str("127.0.0.1");
 
2022
                }
 
2023
            }
 
2024
 
 
2025
            sdp->media[sdp->media_count++] = m;
 
2026
            continue;
 
2027
        }
 
2028
 
 
2029
        /* Get transport address info */
 
2030
        pjmedia_transport_info_init(&tpinfo);
 
2031
        pjmedia_transport_get_info(call_med->tp, &tpinfo);
 
2032
 
 
2033
        /* Ask pjmedia endpoint to create SDP media line */
 
2034
        switch (call_med->type) {
 
2035
        case PJMEDIA_TYPE_AUDIO:
 
2036
            status = pjmedia_endpt_create_audio_sdp(pjsua_var.med_endpt, pool,
 
2037
                                                    &tpinfo.sock_info, 0, &m);
 
2038
            break;
 
2039
#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
 
2040
        case PJMEDIA_TYPE_VIDEO:
 
2041
            status = pjmedia_endpt_create_video_sdp(pjsua_var.med_endpt, pool,
 
2042
                                                    &tpinfo.sock_info, 0, &m);
 
2043
            break;
 
2044
#endif
 
2045
        default:
 
2046
            pj_assert(!"Invalid call_med media type");
 
2047
            return PJ_EBUG;
 
2048
        }
 
2049
 
 
2050
        if (status != PJ_SUCCESS)
 
2051
            return status;
 
2052
 
 
2053
        sdp->media[sdp->media_count++] = m;
 
2054
 
 
2055
        /* Give to transport */
 
2056
        status = pjmedia_transport_encode_sdp(call_med->tp, pool,
 
2057
                                              sdp, rem_sdp, mi);
 
2058
        if (status != PJ_SUCCESS) {
 
2059
            if (sip_err_code) *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE;
 
2060
            return status;
 
2061
        }
 
2062
 
 
2063
#if PJSUA_SDP_SESS_HAS_CONN
 
2064
        /* Copy c= line of the first media to session level,
 
2065
         * if there's none.
 
2066
         */
 
2067
        if (sdp->conn == NULL) {
 
2068
            sdp->conn = pjmedia_sdp_conn_clone(pool, m->conn);
 
2069
        }
 
2070
#endif
 
2071
 
 
2072
        
 
2073
        /* Find media bandwidth info */
 
2074
        for (i = 0; i < m->bandw_count; ++i) {
 
2075
            const pj_str_t STR_BANDW_MODIFIER_TIAS = { "TIAS", 4 };
 
2076
            if (!pj_stricmp(&m->bandw[i]->modifier, &STR_BANDW_MODIFIER_TIAS))
 
2077
            {
 
2078
                tot_bandw_tias += m->bandw[i]->value;
 
2079
                break;
 
2080
            }
 
2081
        }
 
2082
    }
 
2083
 
 
2084
    /* Add NAT info in the SDP */
 
2085
    if (pjsua_var.ua_cfg.nat_type_in_sdp) {
 
2086
        pjmedia_sdp_attr *a;
 
2087
        pj_str_t value;
 
2088
        char nat_info[80];
 
2089
 
 
2090
        value.ptr = nat_info;
 
2091
        if (pjsua_var.ua_cfg.nat_type_in_sdp == 1) {
 
2092
            value.slen = pj_ansi_snprintf(nat_info, sizeof(nat_info),
 
2093
                                          "%d", pjsua_var.nat_type);
 
2094
        } else {
 
2095
            const char *type_name = pj_stun_get_nat_name(pjsua_var.nat_type);
 
2096
            value.slen = pj_ansi_snprintf(nat_info, sizeof(nat_info),
 
2097
                                          "%d %s",
 
2098
                                          pjsua_var.nat_type,
 
2099
                                          type_name);
 
2100
        }
 
2101
 
 
2102
        a = pjmedia_sdp_attr_create(pool, "X-nat", &value);
 
2103
 
 
2104
        pjmedia_sdp_attr_add(&sdp->attr_count, sdp->attr, a);
 
2105
 
 
2106
    }
 
2107
 
 
2108
 
 
2109
    /* Add bandwidth info in session level using bandwidth modifier "AS". */
 
2110
    if (tot_bandw_tias) {
 
2111
        unsigned bandw;
 
2112
        const pj_str_t STR_BANDW_MODIFIER_AS = { "AS", 2 };
 
2113
        pjmedia_sdp_bandw *b;
 
2114
 
 
2115
        /* AS bandwidth = RTP bitrate + RTCP bitrate.
 
2116
         * RTP bitrate  = payload bitrate (total TIAS) + overheads (~16kbps).
 
2117
         * RTCP bitrate = est. 5% of RTP bitrate.
 
2118
         * Note that AS bandwidth is in kbps.
 
2119
         */
 
2120
        bandw = tot_bandw_tias + 16000;
 
2121
        bandw += bandw * 5 / 100;
 
2122
        b = PJ_POOL_ALLOC_T(pool, pjmedia_sdp_bandw);
 
2123
        b->modifier = STR_BANDW_MODIFIER_AS;
 
2124
        b->value = bandw / 1000;
 
2125
        sdp->bandw[sdp->bandw_count++] = b;
 
2126
    }
 
2127
 
 
2128
 
 
2129
#if DISABLED_FOR_TICKET_1185 && defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
 
2130
    /* Check if SRTP is in optional mode and configured to use duplicated
 
2131
     * media, i.e: secured and unsecured version, in the SDP offer.
 
2132
     */
 
2133
    if (!rem_sdp &&
 
2134
        pjsua_var.acc[call->acc_id].cfg.use_srtp == PJMEDIA_SRTP_OPTIONAL &&
 
2135
        pjsua_var.acc[call->acc_id].cfg.srtp_optional_dup_offer)
 
2136
    {
 
2137
        unsigned i;
 
2138
 
 
2139
        for (i = 0; i < sdp->media_count; ++i) {
 
2140
            pjmedia_sdp_media *m = sdp->media[i];
 
2141
 
 
2142
            /* Check if this media is unsecured but has SDP "crypto"
 
2143
             * attribute.
 
2144
             */
 
2145
            if (pj_stricmp2(&m->desc.transport, "RTP/AVP") == 0 &&
 
2146
                pjmedia_sdp_media_find_attr2(m, "crypto", NULL) != NULL)
 
2147
            {
 
2148
                if (i == (unsigned)call->audio_idx &&
 
2149
                    sdp_neg_state == PJMEDIA_SDP_NEG_STATE_DONE)
 
2150
                {
 
2151
                    /* This is a session update, and peer has chosen the
 
2152
                     * unsecured version, so let's make this unsecured too.
 
2153
                     */
 
2154
                    pjmedia_sdp_media_remove_all_attr(m, "crypto");
 
2155
                } else {
 
2156
                    /* This is new offer, duplicate media so we'll have
 
2157
                     * secured (with "RTP/SAVP" transport) and and unsecured
 
2158
                     * versions.
 
2159
                     */
 
2160
                    pjmedia_sdp_media *new_m;
 
2161
 
 
2162
                    /* Duplicate this media and apply secured transport */
 
2163
                    new_m = pjmedia_sdp_media_clone(pool, m);
 
2164
                    pj_strdup2(pool, &new_m->desc.transport, "RTP/SAVP");
 
2165
 
 
2166
                    /* Remove the "crypto" attribute in the unsecured media */
 
2167
                    pjmedia_sdp_media_remove_all_attr(m, "crypto");
 
2168
 
 
2169
                    /* Insert the new media before the unsecured media */
 
2170
                    if (sdp->media_count < PJMEDIA_MAX_SDP_MEDIA) {
 
2171
                        pj_array_insert(sdp->media, sizeof(new_m),
 
2172
                                        sdp->media_count, i, &new_m);
 
2173
                        ++sdp->media_count;
 
2174
                        ++i;
 
2175
                    }
 
2176
                }
 
2177
            }
 
2178
        }
 
2179
    }
 
2180
#endif
 
2181
 
 
2182
    call->rem_offerer = (rem_sdp != NULL);
 
2183
 
 
2184
    /* Notify application */
 
2185
    if (pjsua_var.ua_cfg.cb.on_call_sdp_created) {
 
2186
        (*pjsua_var.ua_cfg.cb.on_call_sdp_created)(call_id, sdp,
 
2187
                                                   pool, rem_sdp);
 
2188
    }
 
2189
 
 
2190
    *p_sdp = sdp;
 
2191
    return PJ_SUCCESS;
 
2192
}
 
2193
 
 
2194
 
 
2195
static void stop_media_stream(pjsua_call *call, unsigned med_idx)
 
2196
{
 
2197
    pjsua_call_media *call_med = &call->media[med_idx];
 
2198
 
 
2199
    /* Check if stream does not exist */
 
2200
    if (med_idx >= call->med_cnt)
 
2201
        return;
 
2202
 
 
2203
    pj_log_push_indent();
 
2204
 
 
2205
    if (call_med->type == PJMEDIA_TYPE_AUDIO) {
 
2206
        pjsua_aud_stop_stream(call_med);
 
2207
    }
 
2208
 
 
2209
#if PJMEDIA_HAS_VIDEO
 
2210
    else if (call_med->type == PJMEDIA_TYPE_VIDEO) {
 
2211
        pjsua_vid_stop_stream(call_med);
 
2212
    }
 
2213
#endif
 
2214
 
 
2215
    PJ_LOG(4,(THIS_FILE, "Media stream call%02d:%d is destroyed",
 
2216
                         call->index, med_idx));
 
2217
    call_med->prev_state = call_med->state;
 
2218
    call_med->state = PJSUA_CALL_MEDIA_NONE;
 
2219
 
 
2220
    /* Try to sync recent changes to provisional media */
 
2221
    if (med_idx < call->med_prov_cnt && 
 
2222
        call->media_prov[med_idx].tp == call_med->tp)
 
2223
    {
 
2224
        pjsua_call_media *prov_med = &call->media_prov[med_idx];
 
2225
 
 
2226
        /* Media state */
 
2227
        prov_med->prev_state = call_med->prev_state;
 
2228
        prov_med->state      = call_med->state;
 
2229
 
 
2230
        /* RTP seq/ts */
 
2231
        prov_med->rtp_tx_seq_ts_set = call_med->rtp_tx_seq_ts_set;
 
2232
        prov_med->rtp_tx_seq        = call_med->rtp_tx_seq;
 
2233
        prov_med->rtp_tx_ts         = call_med->rtp_tx_ts;
 
2234
 
 
2235
        /* Stream */
 
2236
        if (call_med->type == PJMEDIA_TYPE_AUDIO) {
 
2237
            prov_med->strm.a.conf_slot = call_med->strm.a.conf_slot;
 
2238
            prov_med->strm.a.stream    = call_med->strm.a.stream;
 
2239
        }
 
2240
#if PJMEDIA_HAS_VIDEO
 
2241
        else if (call_med->type == PJMEDIA_TYPE_VIDEO) {
 
2242
            prov_med->strm.v.cap_win_id = call_med->strm.v.cap_win_id;
 
2243
            prov_med->strm.v.rdr_win_id = call_med->strm.v.rdr_win_id;
 
2244
            prov_med->strm.v.stream     = call_med->strm.v.stream;
 
2245
        }
 
2246
#endif
 
2247
    }
 
2248
 
 
2249
    pj_log_pop_indent();
 
2250
}
 
2251
 
 
2252
static void stop_media_session(pjsua_call_id call_id)
 
2253
{
 
2254
    pjsua_call *call = &pjsua_var.calls[call_id];
 
2255
    unsigned mi;
 
2256
 
 
2257
    for (mi=0; mi<call->med_cnt; ++mi) {
 
2258
        stop_media_stream(call, mi);
 
2259
    }
 
2260
}
 
2261
 
 
2262
pj_status_t pjsua_media_channel_deinit(pjsua_call_id call_id)
 
2263
{
 
2264
    pjsua_call *call = &pjsua_var.calls[call_id];
 
2265
    unsigned mi;
 
2266
 
 
2267
    for (mi=0; mi<call->med_cnt; ++mi) {
 
2268
        pjsua_call_media *call_med = &call->media[mi];
 
2269
 
 
2270
        if (call_med->tp_st == PJSUA_MED_TP_CREATING) {
 
2271
            /* We will do the deinitialization after media transport
 
2272
             * creation is completed.
 
2273
             */
 
2274
            call->async_call.med_ch_deinit = PJ_TRUE;
 
2275
            return PJ_SUCCESS;
 
2276
        }
 
2277
    }
 
2278
 
 
2279
    PJ_LOG(4,(THIS_FILE, "Call %d: deinitializing media..", call_id));
 
2280
    pj_log_push_indent();
 
2281
 
 
2282
    stop_media_session(call_id);
 
2283
 
 
2284
    /* Clean up media transports */
 
2285
    pjsua_media_prov_clean_up(call_id);
 
2286
    call->med_prov_cnt = 0;
 
2287
    for (mi=0; mi<call->med_cnt; ++mi) {
 
2288
        pjsua_call_media *call_med = &call->media[mi];
 
2289
 
 
2290
        if (call_med->tp_st > PJSUA_MED_TP_IDLE) {
 
2291
            pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_IDLE);
 
2292
            pjmedia_transport_media_stop(call_med->tp);
 
2293
        }
 
2294
 
 
2295
        if (call_med->tp) {
 
2296
            pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_NULL);
 
2297
            pjmedia_transport_close(call_med->tp);
 
2298
            call_med->tp = call_med->tp_orig = NULL;
 
2299
        }
 
2300
        call_med->tp_orig = NULL;
 
2301
    }
 
2302
 
 
2303
    pj_log_pop_indent();
 
2304
 
 
2305
    return PJ_SUCCESS;
 
2306
}
 
2307
 
 
2308
 
 
2309
/* Match codec fmtp. This will compare the values and the order. */
 
2310
static pj_bool_t match_codec_fmtp(const pjmedia_codec_fmtp *fmtp1,
 
2311
                                  const pjmedia_codec_fmtp *fmtp2)
 
2312
{
 
2313
    unsigned i;
 
2314
 
 
2315
    if (fmtp1->cnt != fmtp2->cnt)
 
2316
        return PJ_FALSE;
 
2317
 
 
2318
    for (i = 0; i < fmtp1->cnt; ++i) {
 
2319
        if (pj_stricmp(&fmtp1->param[i].name, &fmtp2->param[i].name))
 
2320
            return PJ_FALSE;
 
2321
        if (pj_stricmp(&fmtp1->param[i].val, &fmtp2->param[i].val))
 
2322
            return PJ_FALSE;
 
2323
    }
 
2324
 
 
2325
    return PJ_TRUE;
 
2326
}
 
2327
 
 
2328
#if PJSUA_MEDIA_HAS_PJMEDIA || PJSUA_THIRD_PARTY_STREAM_HAS_GET_INFO
 
2329
 
 
2330
static pj_bool_t is_ice_running(pjmedia_transport *tp)
 
2331
{
 
2332
    pjmedia_transport_info tpinfo;
 
2333
    pjmedia_ice_transport_info *ice_info;
 
2334
 
 
2335
    pjmedia_transport_info_init(&tpinfo);
 
2336
    pjmedia_transport_get_info(tp, &tpinfo);
 
2337
    ice_info = (pjmedia_ice_transport_info*)
 
2338
               pjmedia_transport_info_get_spc_info(&tpinfo,
 
2339
                                                   PJMEDIA_TRANSPORT_TYPE_ICE);
 
2340
    return (ice_info && ice_info->sess_state == PJ_ICE_STRANS_STATE_RUNNING);
 
2341
}
 
2342
 
 
2343
 
 
2344
static pj_bool_t is_media_changed(const pjsua_call *call,
 
2345
                                  unsigned med_idx,
 
2346
                                  const pjsua_stream_info *new_si_)
 
2347
{
 
2348
    const pjsua_call_media *call_med = &call->media[med_idx];
 
2349
 
 
2350
    /* Check for newly added media */
 
2351
    if (med_idx >= call->med_cnt)
 
2352
        return PJ_TRUE;
 
2353
 
 
2354
    /* Compare media type */
 
2355
    if (call_med->type != new_si_->type)
 
2356
        return PJ_TRUE;
 
2357
 
 
2358
    /* Audio update checks */
 
2359
    if (call_med->type == PJMEDIA_TYPE_AUDIO) {
 
2360
        pjmedia_stream_info the_old_si;
 
2361
        const pjmedia_stream_info *old_si = NULL;
 
2362
        const pjmedia_stream_info *new_si = &new_si_->info.aud;
 
2363
        const pjmedia_codec_info *old_ci = NULL;
 
2364
        const pjmedia_codec_info *new_ci = &new_si->fmt;
 
2365
        const pjmedia_codec_param *old_cp = NULL;
 
2366
        const pjmedia_codec_param *new_cp = new_si->param;
 
2367
 
 
2368
        /* Compare media direction */
 
2369
        if (call_med->dir != new_si->dir)
 
2370
            return PJ_TRUE;
 
2371
 
 
2372
        /* Get current active stream info */
 
2373
        if (call_med->strm.a.stream) {
 
2374
            pjmedia_stream_get_info(call_med->strm.a.stream, &the_old_si);
 
2375
            old_si = &the_old_si;
 
2376
            old_ci = &old_si->fmt;
 
2377
            old_cp = old_si->param;
 
2378
        } else {
 
2379
            /* The stream is inactive. */
 
2380
            return (new_si->dir != PJMEDIA_DIR_NONE);
 
2381
        }
 
2382
 
 
2383
        /* Compare remote RTP address. If ICE is running, change in default
 
2384
         * address can happen after negotiation, this can be handled
 
2385
         * internally by ICE and does not need to cause media restart.
 
2386
         */
 
2387
        if (!is_ice_running(call_med->tp) &&
 
2388
            pj_sockaddr_cmp(&old_si->rem_addr, &new_si->rem_addr))
 
2389
        {
 
2390
            return PJ_TRUE;
 
2391
        }
 
2392
 
 
2393
        /* Compare codec info */
 
2394
        if (pj_stricmp(&old_ci->encoding_name, &new_ci->encoding_name) ||
 
2395
            old_ci->clock_rate != new_ci->clock_rate ||
 
2396
            old_ci->channel_cnt != new_ci->channel_cnt ||
 
2397
            old_si->rx_pt != new_si->rx_pt ||
 
2398
            old_si->tx_pt != new_si->tx_pt ||
 
2399
            old_si->rx_event_pt != new_si->tx_event_pt ||
 
2400
            old_si->tx_event_pt != new_si->tx_event_pt)
 
2401
        {
 
2402
            return PJ_TRUE;
 
2403
        }
 
2404
 
 
2405
        /* Compare codec param */
 
2406
        if (old_cp->setting.frm_per_pkt != new_cp->setting.frm_per_pkt ||
 
2407
            old_cp->setting.vad != new_cp->setting.vad ||
 
2408
            old_cp->setting.cng != new_cp->setting.cng ||
 
2409
            old_cp->setting.plc != new_cp->setting.plc ||
 
2410
            old_cp->setting.penh != new_cp->setting.penh ||
 
2411
            !match_codec_fmtp(&old_cp->setting.dec_fmtp,
 
2412
                              &new_cp->setting.dec_fmtp) ||
 
2413
            !match_codec_fmtp(&old_cp->setting.enc_fmtp,
 
2414
                              &new_cp->setting.enc_fmtp))
 
2415
        {
 
2416
            return PJ_TRUE;
 
2417
        }
 
2418
    }
 
2419
 
 
2420
#if PJMEDIA_HAS_VIDEO
 
2421
    else if (call_med->type == PJMEDIA_TYPE_VIDEO) {
 
2422
        pjmedia_vid_stream_info the_old_si;
 
2423
        const pjmedia_vid_stream_info *old_si = NULL;
 
2424
        const pjmedia_vid_stream_info *new_si = &new_si_->info.vid;
 
2425
        const pjmedia_vid_codec_info *old_ci = NULL;
 
2426
        const pjmedia_vid_codec_info *new_ci = &new_si->codec_info;
 
2427
        const pjmedia_vid_codec_param *old_cp = NULL;
 
2428
        const pjmedia_vid_codec_param *new_cp = new_si->codec_param;
 
2429
 
 
2430
        /* Compare media direction */
 
2431
        if (call_med->dir != new_si->dir)
 
2432
            return PJ_TRUE;
 
2433
 
 
2434
        /* Get current active stream info */
 
2435
        if (call_med->strm.v.stream) {
 
2436
            pjmedia_vid_stream_get_info(call_med->strm.v.stream, &the_old_si);
 
2437
            old_si = &the_old_si;
 
2438
            old_ci = &old_si->codec_info;
 
2439
            old_cp = old_si->codec_param;
 
2440
        } else {
 
2441
            /* The stream is inactive. */
 
2442
            return (new_si->dir != PJMEDIA_DIR_NONE);
 
2443
        }
 
2444
 
 
2445
        /* Compare remote RTP address. If ICE is running, change in default
 
2446
         * address can happen after negotiation, this can be handled
 
2447
         * internally by ICE and does not need to cause media restart.
 
2448
         */
 
2449
        if (!is_ice_running(call_med->tp) &&
 
2450
            pj_sockaddr_cmp(&old_si->rem_addr, &new_si->rem_addr))
 
2451
        {
 
2452
            return PJ_TRUE;
 
2453
        }
 
2454
 
 
2455
        /* Compare codec info */
 
2456
        if (pj_stricmp(&old_ci->encoding_name, &new_ci->encoding_name) ||
 
2457
            old_si->rx_pt != new_si->rx_pt ||
 
2458
            old_si->tx_pt != new_si->tx_pt)
 
2459
        {
 
2460
            return PJ_TRUE;
 
2461
        }
 
2462
 
 
2463
        /* Compare codec param */
 
2464
        if (/* old_cp->enc_mtu != new_cp->enc_mtu || */
 
2465
            pj_memcmp(&old_cp->enc_fmt.det, &new_cp->enc_fmt.det,
 
2466
                      sizeof(pjmedia_video_format_detail)) ||
 
2467
            !match_codec_fmtp(&old_cp->dec_fmtp, &new_cp->dec_fmtp) ||
 
2468
            !match_codec_fmtp(&old_cp->enc_fmtp, &new_cp->enc_fmtp))
 
2469
        {
 
2470
            return PJ_TRUE;
 
2471
        }
 
2472
    }
 
2473
 
 
2474
#endif
 
2475
 
 
2476
    else {
 
2477
        /* Just return PJ_TRUE for other media type */
 
2478
        return PJ_TRUE;
 
2479
    }
 
2480
 
 
2481
    return PJ_FALSE;
 
2482
}
 
2483
 
 
2484
#else /* PJSUA_MEDIA_HAS_PJMEDIA || PJSUA_THIRD_PARTY_STREAM_HAS_GET_INFO */
 
2485
 
 
2486
static pj_bool_t is_media_changed(const pjsua_call *call,
 
2487
                                  unsigned med_idx,
 
2488
                                  const pjsua_stream_info *new_si_)
 
2489
{
 
2490
    PJ_UNUSED_ARG(call);
 
2491
    PJ_UNUSED_ARG(med_idx);
 
2492
    PJ_UNUSED_ARG(new_si_);
 
2493
    /* Always assume that media has been changed */
 
2494
    return PJ_TRUE;
 
2495
}
 
2496
 
 
2497
#endif /* PJSUA_MEDIA_HAS_PJMEDIA || PJSUA_THIRD_PARTY_STREAM_HAS_GET_INFO */
 
2498
 
 
2499
 
 
2500
pj_status_t pjsua_media_channel_update(pjsua_call_id call_id,
 
2501
                                       const pjmedia_sdp_session *local_sdp,
 
2502
                                       const pjmedia_sdp_session *remote_sdp)
 
2503
{
 
2504
    pjsua_call *call = &pjsua_var.calls[call_id];
 
2505
    pjsua_acc *acc = &pjsua_var.acc[call->acc_id];
 
2506
    pj_pool_t *tmp_pool = call->inv->pool_prov;
 
2507
    unsigned mi;
 
2508
    pj_bool_t got_media = PJ_FALSE;
 
2509
    pj_status_t status = PJ_SUCCESS;
 
2510
 
 
2511
    const pj_str_t STR_AUDIO = { "audio", 5 };
 
2512
    const pj_str_t STR_VIDEO = { "video", 5 };
 
2513
    pj_uint8_t maudidx[PJSUA_MAX_CALL_MEDIA];
 
2514
    unsigned maudcnt = PJ_ARRAY_SIZE(maudidx);
 
2515
    unsigned mtotaudcnt = PJ_ARRAY_SIZE(maudidx);
 
2516
    pj_uint8_t mvididx[PJSUA_MAX_CALL_MEDIA];
 
2517
    unsigned mvidcnt = PJ_ARRAY_SIZE(mvididx);
 
2518
    unsigned mtotvidcnt = PJ_ARRAY_SIZE(mvididx);
 
2519
    pj_bool_t need_renego_sdp = PJ_FALSE;
 
2520
 
 
2521
    if (pjsua_get_state() != PJSUA_STATE_RUNNING)
 
2522
        return PJ_EBUSY;
 
2523
 
 
2524
    PJ_LOG(4,(THIS_FILE, "Call %d: updating media..", call_id));
 
2525
    pj_log_push_indent();
 
2526
 
 
2527
    /* Destroy existing media session, if any. */
 
2528
    //stop_media_session(call->index);
 
2529
 
 
2530
    /* Call media count must be at least equal to SDP media. Note that
 
2531
     * it may not be equal when remote removed any SDP media line.
 
2532
     */
 
2533
    pj_assert(call->med_prov_cnt >= local_sdp->media_count);
 
2534
 
 
2535
    /* Reset audio_idx first */
 
2536
    call->audio_idx = -1;
 
2537
 
 
2538
    /* Sort audio/video based on "quality" */
 
2539
    sort_media(local_sdp, &STR_AUDIO, acc->cfg.use_srtp,
 
2540
               maudidx, &maudcnt, &mtotaudcnt);
 
2541
#if PJMEDIA_HAS_VIDEO
 
2542
    sort_media(local_sdp, &STR_VIDEO, acc->cfg.use_srtp,
 
2543
               mvididx, &mvidcnt, &mtotvidcnt);
 
2544
#else
 
2545
    PJ_UNUSED_ARG(STR_VIDEO);
 
2546
    mvidcnt = mtotvidcnt = 0;
 
2547
#endif
 
2548
 
 
2549
    /* Applying media count limitation. Note that in generating SDP answer,
 
2550
     * no media count limitation applied, as we didn't know yet which media
 
2551
     * would pass the SDP negotiation.
 
2552
     */
 
2553
    if (maudcnt > call->opt.aud_cnt || mvidcnt > call->opt.vid_cnt)
 
2554
    {
 
2555
        pjmedia_sdp_session *local_sdp2;
 
2556
 
 
2557
        maudcnt = PJ_MIN(maudcnt, call->opt.aud_cnt);
 
2558
        mvidcnt = PJ_MIN(mvidcnt, call->opt.vid_cnt);
 
2559
        local_sdp2 = pjmedia_sdp_session_clone(tmp_pool, local_sdp);
 
2560
 
 
2561
        for (mi=0; mi < local_sdp2->media_count; ++mi) {
 
2562
            pjmedia_sdp_media *m = local_sdp2->media[mi];
 
2563
 
 
2564
            if (m->desc.port == 0 ||
 
2565
                pj_memchr(maudidx, mi, maudcnt*sizeof(maudidx[0])) ||
 
2566
                pj_memchr(mvididx, mi, mvidcnt*sizeof(mvididx[0])))
 
2567
            {
 
2568
                continue;
 
2569
            }
 
2570
            
 
2571
            /* Deactivate this media */
 
2572
            pjmedia_sdp_media_deactivate(tmp_pool, m);
 
2573
        }
 
2574
 
 
2575
        local_sdp = local_sdp2;
 
2576
        need_renego_sdp = PJ_TRUE;
 
2577
    }
 
2578
 
 
2579
    /* Process each media stream */
 
2580
    for (mi=0; mi < call->med_prov_cnt; ++mi) {
 
2581
        pjsua_call_media *call_med = &call->media_prov[mi];
 
2582
        pj_bool_t media_changed = PJ_FALSE;
 
2583
 
 
2584
        if (mi >= local_sdp->media_count ||
 
2585
            mi >= remote_sdp->media_count)
 
2586
        {
 
2587
            /* This may happen when remote removed any SDP media lines in
 
2588
             * its re-offer.
 
2589
             */
 
2590
 
 
2591
            /* Stop stream */
 
2592
            stop_media_stream(call, mi);
 
2593
 
 
2594
            /* Close the media transport */
 
2595
            if (call_med->tp) {
 
2596
                pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_NULL);
 
2597
                pjmedia_transport_close(call_med->tp);
 
2598
                call_med->tp = call_med->tp_orig = NULL;
 
2599
            }
 
2600
            continue;
 
2601
#if 0
 
2602
            /* Something is wrong */
 
2603
            PJ_LOG(1,(THIS_FILE, "Error updating media for call %d: "
 
2604
                      "invalid media index %d in SDP", call_id, mi));
 
2605
            status = PJMEDIA_SDP_EINSDP;
 
2606
            goto on_error;
 
2607
#endif
 
2608
        }
 
2609
 
 
2610
        /* Apply media update action */
 
2611
        if (call_med->type==PJMEDIA_TYPE_AUDIO) {
 
2612
            pjmedia_stream_info the_si, *si = &the_si;
 
2613
            pjsua_stream_info stream_info;
 
2614
 
 
2615
            status = pjmedia_stream_info_from_sdp(
 
2616
                                        si, tmp_pool, pjsua_var.med_endpt,
 
2617
                                        local_sdp, remote_sdp, mi);
 
2618
            if (status != PJ_SUCCESS) {
 
2619
                PJ_PERROR(1,(THIS_FILE, status,
 
2620
                             "pjmedia_stream_info_from_sdp() failed "
 
2621
                                 "for call_id %d media %d",
 
2622
                             call_id, mi));
 
2623
                continue;
 
2624
            }
 
2625
 
 
2626
            /* Codec parameter of stream info (si->param) can be NULL if
 
2627
             * the stream is rejected or disabled.
 
2628
             */
 
2629
            /* Override ptime, if this option is specified. */
 
2630
            if (pjsua_var.media_cfg.ptime != 0 && si->param) {
 
2631
                si->param->setting.frm_per_pkt = (pj_uint8_t)
 
2632
                    (pjsua_var.media_cfg.ptime / si->param->info.frm_ptime);
 
2633
                if (si->param->setting.frm_per_pkt == 0)
 
2634
                    si->param->setting.frm_per_pkt = 1;
 
2635
            }
 
2636
 
 
2637
            /* Disable VAD, if this option is specified. */
 
2638
            if (pjsua_var.media_cfg.no_vad && si->param) {
 
2639
                si->param->setting.vad = 0;
 
2640
            }
 
2641
 
 
2642
            /* Check if this media is changed */
 
2643
            stream_info.type = PJMEDIA_TYPE_AUDIO;
 
2644
            stream_info.info.aud = the_si;
 
2645
            if (pjsua_var.media_cfg.no_smart_media_update ||
 
2646
                is_media_changed(call, mi, &stream_info))
 
2647
            {
 
2648
                media_changed = PJ_TRUE;
 
2649
                /* Stop the media */
 
2650
                stop_media_stream(call, mi);
 
2651
            } else {
 
2652
                PJ_LOG(4,(THIS_FILE, "Call %d: stream #%d (audio) unchanged.",
 
2653
                          call_id, mi));
 
2654
            }
 
2655
 
 
2656
            /* Check if no media is active */
 
2657
            if (si->dir == PJMEDIA_DIR_NONE) {
 
2658
 
 
2659
                /* Update call media state and direction */
 
2660
                call_med->state = PJSUA_CALL_MEDIA_NONE;
 
2661
                call_med->dir = PJMEDIA_DIR_NONE;
 
2662
 
 
2663
            } else {
 
2664
                pjmedia_transport_info tp_info;
 
2665
                pjmedia_srtp_info *srtp_info;
 
2666
 
 
2667
                /* Start/restart media transport based on info in SDP */
 
2668
                status = pjmedia_transport_media_start(call_med->tp,
 
2669
                                                       tmp_pool, local_sdp,
 
2670
                                                       remote_sdp, mi);
 
2671
                if (status != PJ_SUCCESS) {
 
2672
                    PJ_PERROR(1,(THIS_FILE, status,
 
2673
                                 "pjmedia_transport_media_start() failed "
 
2674
                                     "for call_id %d media %d",
 
2675
                                 call_id, mi));
 
2676
                    continue;
 
2677
                }
 
2678
 
 
2679
                pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_RUNNING);
 
2680
 
 
2681
                /* Get remote SRTP usage policy */
 
2682
                pjmedia_transport_info_init(&tp_info);
 
2683
                pjmedia_transport_get_info(call_med->tp, &tp_info);
 
2684
                srtp_info = (pjmedia_srtp_info*)
 
2685
                            pjmedia_transport_info_get_spc_info(
 
2686
                                    &tp_info, PJMEDIA_TRANSPORT_TYPE_SRTP);
 
2687
                if (srtp_info) {
 
2688
                    call_med->rem_srtp_use = srtp_info->peer_use;
 
2689
                }
 
2690
 
 
2691
                /* Update audio channel */
 
2692
                if (media_changed) {
 
2693
                    status = pjsua_aud_channel_update(call_med,
 
2694
                                                      call->inv->pool, si,
 
2695
                                                      local_sdp, remote_sdp);
 
2696
                    if (status != PJ_SUCCESS) {
 
2697
                        PJ_PERROR(1,(THIS_FILE, status,
 
2698
                                     "pjsua_aud_channel_update() failed "
 
2699
                                         "for call_id %d media %d",
 
2700
                                     call_id, mi));
 
2701
                        continue;
 
2702
                    }
 
2703
                }
 
2704
 
 
2705
                /* Call media direction */
 
2706
                call_med->dir = si->dir;
 
2707
 
 
2708
                /* Call media state */
 
2709
                if (call->local_hold)
 
2710
                    call_med->state = PJSUA_CALL_MEDIA_LOCAL_HOLD;
 
2711
                else if (call_med->dir == PJMEDIA_DIR_DECODING)
 
2712
                    call_med->state = PJSUA_CALL_MEDIA_REMOTE_HOLD;
 
2713
                else
 
2714
                    call_med->state = PJSUA_CALL_MEDIA_ACTIVE;
 
2715
            }
 
2716
 
 
2717
            /* Print info. */
 
2718
            if (status == PJ_SUCCESS) {
 
2719
                char info[80];
 
2720
                int info_len = 0;
 
2721
                int len;
 
2722
                const char *dir;
 
2723
 
 
2724
                switch (si->dir) {
 
2725
                case PJMEDIA_DIR_NONE:
 
2726
                    dir = "inactive";
 
2727
                    break;
 
2728
                case PJMEDIA_DIR_ENCODING:
 
2729
                    dir = "sendonly";
 
2730
                    break;
 
2731
                case PJMEDIA_DIR_DECODING:
 
2732
                    dir = "recvonly";
 
2733
                    break;
 
2734
                case PJMEDIA_DIR_ENCODING_DECODING:
 
2735
                    dir = "sendrecv";
 
2736
                    break;
 
2737
                default:
 
2738
                    dir = "unknown";
 
2739
                    break;
 
2740
                }
 
2741
                len = pj_ansi_sprintf( info+info_len,
 
2742
                                       ", stream #%d: %.*s (%s)", mi,
 
2743
                                       (int)si->fmt.encoding_name.slen,
 
2744
                                       si->fmt.encoding_name.ptr,
 
2745
                                       dir);
 
2746
                if (len > 0)
 
2747
                    info_len += len;
 
2748
                PJ_LOG(4,(THIS_FILE,"Audio updated%s", info));
 
2749
            }
 
2750
 
 
2751
 
 
2752
            if (call->audio_idx==-1 && status==PJ_SUCCESS &&
 
2753
                si->dir != PJMEDIA_DIR_NONE)
 
2754
            {
 
2755
                call->audio_idx = mi;
 
2756
            }
 
2757
 
 
2758
#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
 
2759
        } else if (call_med->type==PJMEDIA_TYPE_VIDEO) {
 
2760
            pjmedia_vid_stream_info the_si, *si = &the_si;
 
2761
            pjsua_stream_info stream_info;
 
2762
 
 
2763
            status = pjmedia_vid_stream_info_from_sdp(
 
2764
                                        si, tmp_pool, pjsua_var.med_endpt,
 
2765
                                        local_sdp, remote_sdp, mi);
 
2766
            if (status != PJ_SUCCESS) {
 
2767
                PJ_PERROR(1,(THIS_FILE, status,
 
2768
                             "pjmedia_vid_stream_info_from_sdp() failed "
 
2769
                                 "for call_id %d media %d",
 
2770
                             call_id, mi));
 
2771
                continue;
 
2772
            }
 
2773
 
 
2774
            /* Check if this media is changed */
 
2775
            stream_info.type = PJMEDIA_TYPE_VIDEO;
 
2776
            stream_info.info.vid = the_si;
 
2777
            if (is_media_changed(call, mi, &stream_info)) {
 
2778
                media_changed = PJ_TRUE;
 
2779
                /* Stop the media */
 
2780
                stop_media_stream(call, mi);
 
2781
            } else {
 
2782
                PJ_LOG(4,(THIS_FILE, "Call %d: stream #%d (video) unchanged.",
 
2783
                          call_id, mi));
 
2784
            }
 
2785
 
 
2786
            /* Check if no media is active */
 
2787
            if (si->dir == PJMEDIA_DIR_NONE) {
 
2788
 
 
2789
                /* Update call media state and direction */
 
2790
                call_med->state = PJSUA_CALL_MEDIA_NONE;
 
2791
                call_med->dir = PJMEDIA_DIR_NONE;
 
2792
 
 
2793
            } else {
 
2794
                pjmedia_transport_info tp_info;
 
2795
                pjmedia_srtp_info *srtp_info;
 
2796
 
 
2797
                /* Start/restart media transport */
 
2798
                status = pjmedia_transport_media_start(call_med->tp,
 
2799
                                                       tmp_pool, local_sdp,
 
2800
                                                       remote_sdp, mi);
 
2801
                if (status != PJ_SUCCESS) {
 
2802
                    PJ_PERROR(1,(THIS_FILE, status,
 
2803
                                 "pjmedia_transport_media_start() failed "
 
2804
                                     "for call_id %d media %d",
 
2805
                                 call_id, mi));
 
2806
                    continue;
 
2807
                }
 
2808
 
 
2809
                pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_RUNNING);
 
2810
 
 
2811
                /* Get remote SRTP usage policy */
 
2812
                pjmedia_transport_info_init(&tp_info);
 
2813
                pjmedia_transport_get_info(call_med->tp, &tp_info);
 
2814
                srtp_info = (pjmedia_srtp_info*)
 
2815
                            pjmedia_transport_info_get_spc_info(
 
2816
                                    &tp_info, PJMEDIA_TRANSPORT_TYPE_SRTP);
 
2817
                if (srtp_info) {
 
2818
                    call_med->rem_srtp_use = srtp_info->peer_use;
 
2819
                }
 
2820
 
 
2821
                /* Update audio channel */
 
2822
                if (media_changed) {
 
2823
                    status = pjsua_vid_channel_update(call_med,
 
2824
                                                      call->inv->pool, si,
 
2825
                                                      local_sdp, remote_sdp);
 
2826
                    if (status != PJ_SUCCESS) {
 
2827
                        PJ_PERROR(1,(THIS_FILE, status,
 
2828
                                     "pjsua_vid_channel_update() failed "
 
2829
                                         "for call_id %d media %d",
 
2830
                                     call_id, mi));
 
2831
                        continue;
 
2832
                    }
 
2833
                }
 
2834
 
 
2835
                /* Call media direction */
 
2836
                call_med->dir = si->dir;
 
2837
 
 
2838
                /* Call media state */
 
2839
                if (call->local_hold)
 
2840
                    call_med->state = PJSUA_CALL_MEDIA_LOCAL_HOLD;
 
2841
                else if (call_med->dir == PJMEDIA_DIR_DECODING)
 
2842
                    call_med->state = PJSUA_CALL_MEDIA_REMOTE_HOLD;
 
2843
                else
 
2844
                    call_med->state = PJSUA_CALL_MEDIA_ACTIVE;
 
2845
            }
 
2846
 
 
2847
            /* Print info. */
 
2848
            {
 
2849
                char info[80];
 
2850
                int info_len = 0;
 
2851
                int len;
 
2852
                const char *dir;
 
2853
 
 
2854
                switch (si->dir) {
 
2855
                case PJMEDIA_DIR_NONE:
 
2856
                    dir = "inactive";
 
2857
                    break;
 
2858
                case PJMEDIA_DIR_ENCODING:
 
2859
                    dir = "sendonly";
 
2860
                    break;
 
2861
                case PJMEDIA_DIR_DECODING:
 
2862
                    dir = "recvonly";
 
2863
                    break;
 
2864
                case PJMEDIA_DIR_ENCODING_DECODING:
 
2865
                    dir = "sendrecv";
 
2866
                    break;
 
2867
                default:
 
2868
                    dir = "unknown";
 
2869
                    break;
 
2870
                }
 
2871
                len = pj_ansi_sprintf( info+info_len,
 
2872
                                       ", stream #%d: %.*s (%s)", mi,
 
2873
                                       (int)si->codec_info.encoding_name.slen,
 
2874
                                       si->codec_info.encoding_name.ptr,
 
2875
                                       dir);
 
2876
                if (len > 0)
 
2877
                    info_len += len;
 
2878
                PJ_LOG(4,(THIS_FILE,"Video updated%s", info));
 
2879
            }
 
2880
 
 
2881
#endif
 
2882
        } else {
 
2883
            status = PJMEDIA_EINVALIMEDIATYPE;
 
2884
        }
 
2885
 
 
2886
        /* Close the transport of deactivated media, need this here as media
 
2887
         * can be deactivated by the SDP negotiation and the max media count
 
2888
         * (account) setting.
 
2889
         */
 
2890
        if (local_sdp->media[mi]->desc.port==0 && call_med->tp) {
 
2891
            pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_NULL);
 
2892
            pjmedia_transport_close(call_med->tp);
 
2893
            call_med->tp = call_med->tp_orig = NULL;
 
2894
        }
 
2895
 
 
2896
        if (status != PJ_SUCCESS) {
 
2897
            PJ_PERROR(1,(THIS_FILE, status, "Error updating media call%02d:%d",
 
2898
                         call_id, mi));
 
2899
        } else {
 
2900
            got_media = PJ_TRUE;
 
2901
        }
 
2902
    }
 
2903
 
 
2904
    /* Update call media from provisional media */
 
2905
    call->med_cnt = call->med_prov_cnt;
 
2906
    pj_memcpy(call->media, call->media_prov,
 
2907
              sizeof(call->media_prov[0]) * call->med_prov_cnt);
 
2908
 
 
2909
    /* Perform SDP re-negotiation if needed. */
 
2910
    if (got_media && need_renego_sdp) {
 
2911
        pjmedia_sdp_neg *neg = call->inv->neg;
 
2912
 
 
2913
        /* This should only happen when we are the answerer. */
 
2914
        PJ_ASSERT_RETURN(neg && !pjmedia_sdp_neg_was_answer_remote(neg),
 
2915
                         PJMEDIA_SDPNEG_EINSTATE);
 
2916
        
 
2917
        status = pjmedia_sdp_neg_set_remote_offer(tmp_pool, neg, remote_sdp);
 
2918
        if (status != PJ_SUCCESS)
 
2919
            goto on_error;
 
2920
 
 
2921
        status = pjmedia_sdp_neg_set_local_answer(tmp_pool, neg, local_sdp);
 
2922
        if (status != PJ_SUCCESS)
 
2923
            goto on_error;
 
2924
 
 
2925
        status = pjmedia_sdp_neg_negotiate(tmp_pool, neg, 0);
 
2926
        if (status != PJ_SUCCESS)
 
2927
            goto on_error;
 
2928
    }
 
2929
 
 
2930
    pj_log_pop_indent();
 
2931
    return (got_media? PJ_SUCCESS : PJMEDIA_SDPNEG_ENOMEDIA);
 
2932
 
 
2933
on_error:
 
2934
    pj_log_pop_indent();
 
2935
    return status;
 
2936
}
 
2937
 
 
2938
/*****************************************************************************
 
2939
 * Codecs.
 
2940
 */
 
2941
 
 
2942
/*
 
2943
 * Enum all supported codecs in the system.
 
2944
 */
 
2945
PJ_DEF(pj_status_t) pjsua_enum_codecs( pjsua_codec_info id[],
 
2946
                                       unsigned *p_count )
 
2947
{
 
2948
    pjmedia_codec_mgr *codec_mgr;
 
2949
    pjmedia_codec_info info[32];
 
2950
    unsigned i, count, prio[32];
 
2951
    pj_status_t status;
 
2952
 
 
2953
    codec_mgr = pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt);
 
2954
    count = PJ_ARRAY_SIZE(info);
 
2955
    status = pjmedia_codec_mgr_enum_codecs( codec_mgr, &count, info, prio);
 
2956
    if (status != PJ_SUCCESS) {
 
2957
        *p_count = 0;
 
2958
        return status;
 
2959
    }
 
2960
 
 
2961
    if (count > *p_count) count = *p_count;
 
2962
 
 
2963
    for (i=0; i<count; ++i) {
 
2964
        pj_bzero(&id[i], sizeof(pjsua_codec_info));
 
2965
 
 
2966
        pjmedia_codec_info_to_id(&info[i], id[i].buf_, sizeof(id[i].buf_));
 
2967
        id[i].codec_id = pj_str(id[i].buf_);
 
2968
        id[i].priority = (pj_uint8_t) prio[i];
 
2969
    }
 
2970
 
 
2971
    *p_count = count;
 
2972
 
 
2973
    return PJ_SUCCESS;
 
2974
}
 
2975
 
 
2976
 
 
2977
/*
 
2978
 * Change codec priority.
 
2979
 */
 
2980
PJ_DEF(pj_status_t) pjsua_codec_set_priority( const pj_str_t *codec_id,
 
2981
                                              pj_uint8_t priority )
 
2982
{
 
2983
    const pj_str_t all = { NULL, 0 };
 
2984
    pjmedia_codec_mgr *codec_mgr;
 
2985
 
 
2986
    codec_mgr = pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt);
 
2987
 
 
2988
    if (codec_id->slen==1 && *codec_id->ptr=='*')
 
2989
        codec_id = &all;
 
2990
 
 
2991
    return pjmedia_codec_mgr_set_codec_priority(codec_mgr, codec_id, 
 
2992
                                                priority);
 
2993
}
 
2994
 
 
2995
 
 
2996
/*
 
2997
 * Get codec parameters.
 
2998
 */
 
2999
PJ_DEF(pj_status_t) pjsua_codec_get_param( const pj_str_t *codec_id,
 
3000
                                           pjmedia_codec_param *param )
 
3001
{
 
3002
    const pj_str_t all = { NULL, 0 };
 
3003
    const pjmedia_codec_info *info;
 
3004
    pjmedia_codec_mgr *codec_mgr;
 
3005
    unsigned count = 1;
 
3006
    pj_status_t status;
 
3007
 
 
3008
    codec_mgr = pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt);
 
3009
 
 
3010
    if (codec_id->slen==1 && *codec_id->ptr=='*')
 
3011
        codec_id = &all;
 
3012
 
 
3013
    status = pjmedia_codec_mgr_find_codecs_by_id(codec_mgr, codec_id,
 
3014
                                                 &count, &info, NULL);
 
3015
    if (status != PJ_SUCCESS)
 
3016
        return status;
 
3017
 
 
3018
    if (count != 1)
 
3019
        return (count > 1? PJ_ETOOMANY : PJ_ENOTFOUND);
 
3020
 
 
3021
    status = pjmedia_codec_mgr_get_default_param( codec_mgr, info, param);
 
3022
    return status;
 
3023
}
 
3024
 
 
3025
 
 
3026
/*
 
3027
 * Set codec parameters.
 
3028
 */
 
3029
PJ_DEF(pj_status_t) pjsua_codec_set_param( const pj_str_t *codec_id,
 
3030
                                           const pjmedia_codec_param *param)
 
3031
{
 
3032
    const pjmedia_codec_info *info[2];
 
3033
    pjmedia_codec_mgr *codec_mgr;
 
3034
    unsigned count = 2;
 
3035
    pj_status_t status;
 
3036
 
 
3037
    codec_mgr = pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt);
 
3038
 
 
3039
    status = pjmedia_codec_mgr_find_codecs_by_id(codec_mgr, codec_id,
 
3040
                                                 &count, info, NULL);
 
3041
    if (status != PJ_SUCCESS)
 
3042
        return status;
 
3043
 
 
3044
    /* Codec ID should be specific, except for G.722.1 */
 
3045
    if (count > 1 && 
 
3046
        pj_strnicmp2(codec_id, "G7221/16", 8) != 0 &&
 
3047
        pj_strnicmp2(codec_id, "G7221/32", 8) != 0)
 
3048
    {
 
3049
        pj_assert(!"Codec ID is not specific");
 
3050
        return PJ_ETOOMANY;
 
3051
    }
 
3052
 
 
3053
    status = pjmedia_codec_mgr_set_default_param(codec_mgr, info[0], param);
 
3054
    return status;
 
3055
}
 
3056
 
 
3057
 
 
3058
pj_status_t pjsua_media_apply_xml_control(pjsua_call_id call_id,
 
3059
                                          const pj_str_t *xml_st)
 
3060
{
 
3061
#if PJMEDIA_HAS_VIDEO
 
3062
    pjsua_call *call = &pjsua_var.calls[call_id];
 
3063
    const pj_str_t PICT_FAST_UPDATE = {"picture_fast_update", 19};
 
3064
 
 
3065
    if (pj_strstr(xml_st, &PICT_FAST_UPDATE)) {
 
3066
        unsigned i;
 
3067
 
 
3068
        PJ_LOG(4,(THIS_FILE, "Received keyframe request via SIP INFO"));
 
3069
 
 
3070
        for (i = 0; i < call->med_cnt; ++i) {
 
3071
            pjsua_call_media *cm = &call->media[i];
 
3072
            if (cm->type != PJMEDIA_TYPE_VIDEO || !cm->strm.v.stream)
 
3073
                continue;
 
3074
 
 
3075
            pjmedia_vid_stream_send_keyframe(cm->strm.v.stream);
 
3076
        }
 
3077
 
 
3078
        return PJ_SUCCESS;
 
3079
    }
 
3080
#endif
 
3081
 
 
3082
    /* Just to avoid compiler warning of unused var */
 
3083
    PJ_UNUSED_ARG(call_id);
 
3084
    PJ_UNUSED_ARG(xml_st);
 
3085
 
 
3086
    return PJ_ENOTSUP;
 
3087
}
 
3088