blob: 8984f8f549bb039a4b2c7df3af649f61e818ea6f [file] [log] [blame]
Tristan Matthews0a329cc2013-07-17 13:20:14 -04001/* $Id: pjsua_call.c 4561 2013-07-15 01:29:03Z ming $ */
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_call.c"
25
26
27/* Retry interval of sending re-INVITE for locking a codec when remote
28 * SDP answer contains multiple codec, in milliseconds.
29 */
30#define LOCK_CODEC_RETRY_INTERVAL 200
31
32/*
33 * Max UPDATE/re-INVITE retry to lock codec
34 */
35#define LOCK_CODEC_MAX_RETRY 5
36
37
38/*
39 * The INFO method.
40 */
41const pjsip_method pjsip_info_method =
42{
43 PJSIP_OTHER_METHOD,
44 { "INFO", 4 }
45};
46
47
48/* This callback receives notification from invite session when the
49 * session state has changed.
50 */
51static void pjsua_call_on_state_changed(pjsip_inv_session *inv,
52 pjsip_event *e);
53
54/* This callback is called by invite session framework when UAC session
55 * has forked.
56 */
57static void pjsua_call_on_forked( pjsip_inv_session *inv,
58 pjsip_event *e);
59
60/*
61 * Callback to be called when SDP offer/answer negotiation has just completed
62 * in the session. This function will start/update media if negotiation
63 * has succeeded.
64 */
65static void pjsua_call_on_media_update(pjsip_inv_session *inv,
66 pj_status_t status);
67
68/*
69 * Called when session received new offer.
70 */
71static void pjsua_call_on_rx_offer(pjsip_inv_session *inv,
72 const pjmedia_sdp_session *offer);
73
74/*
75 * Called to generate new offer.
76 */
77static void pjsua_call_on_create_offer(pjsip_inv_session *inv,
78 pjmedia_sdp_session **offer);
79
80/*
81 * This callback is called when transaction state has changed in INVITE
82 * session. We use this to trap:
83 * - incoming REFER request.
84 * - incoming MESSAGE request.
85 */
86static void pjsua_call_on_tsx_state_changed(pjsip_inv_session *inv,
87 pjsip_transaction *tsx,
88 pjsip_event *e);
89
90/*
91 * Redirection handler.
92 */
93static pjsip_redirect_op pjsua_call_on_redirected(pjsip_inv_session *inv,
94 const pjsip_uri *target,
95 const pjsip_event *e);
96
97
98/* Create SDP for call hold. */
99static pj_status_t create_sdp_of_call_hold(pjsua_call *call,
100 pjmedia_sdp_session **p_sdp);
101
102/*
103 * Callback called by event framework when the xfer subscription state
104 * has changed.
105 */
106static void xfer_client_on_evsub_state( pjsip_evsub *sub, pjsip_event *event);
107static void xfer_server_on_evsub_state( pjsip_evsub *sub, pjsip_event *event);
108
109/* Timer callback to send re-INVITE/UPDATE to lock codec or ICE update */
110static void reinv_timer_cb(pj_timer_heap_t *th, pj_timer_entry *entry);
111
112/* Check and send reinvite for lock codec and ICE update */
113static pj_status_t process_pending_reinvite(pjsua_call *call);
114
115/*
116 * Reset call descriptor.
117 */
118static void reset_call(pjsua_call_id id)
119{
120 pjsua_call *call = &pjsua_var.calls[id];
121 unsigned i;
122
123 pj_bzero(call, sizeof(*call));
124 call->index = id;
125 call->last_text.ptr = call->last_text_buf_;
126 for (i=0; i<PJ_ARRAY_SIZE(call->media); ++i) {
127 pjsua_call_media *call_med = &call->media[i];
128 call_med->ssrc = pj_rand();
129 call_med->strm.a.conf_slot = PJSUA_INVALID_ID;
130 call_med->strm.v.cap_win_id = PJSUA_INVALID_ID;
131 call_med->strm.v.rdr_win_id = PJSUA_INVALID_ID;
132 call_med->call = call;
133 call_med->idx = i;
134 call_med->tp_auto_del = PJ_TRUE;
135 }
136 pjsua_call_setting_default(&call->opt);
137 pj_timer_entry_init(&call->reinv_timer, PJ_FALSE,
138 (void*)(pj_size_t)id, &reinv_timer_cb);
139}
140
141
142/*
143 * Init call subsystem.
144 */
145pj_status_t pjsua_call_subsys_init(const pjsua_config *cfg)
146{
147 pjsip_inv_callback inv_cb;
148 unsigned i;
149 const pj_str_t str_norefersub = { "norefersub", 10 };
150 pj_status_t status;
151
152 /* Init calls array. */
153 for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.calls); ++i)
154 reset_call(i);
155
156 /* Copy config */
157 pjsua_config_dup(pjsua_var.pool, &pjsua_var.ua_cfg, cfg);
158
159 /* Verify settings */
160 if (pjsua_var.ua_cfg.max_calls >= PJSUA_MAX_CALLS) {
161 pjsua_var.ua_cfg.max_calls = PJSUA_MAX_CALLS;
162 }
163
164 /* Check the route URI's and force loose route if required */
165 for (i=0; i<pjsua_var.ua_cfg.outbound_proxy_cnt; ++i) {
166 status = normalize_route_uri(pjsua_var.pool,
167 &pjsua_var.ua_cfg.outbound_proxy[i]);
168 if (status != PJ_SUCCESS)
169 return status;
170 }
171
172 /* Initialize invite session callback. */
173 pj_bzero(&inv_cb, sizeof(inv_cb));
174 inv_cb.on_state_changed = &pjsua_call_on_state_changed;
175 inv_cb.on_new_session = &pjsua_call_on_forked;
176 inv_cb.on_media_update = &pjsua_call_on_media_update;
177 inv_cb.on_rx_offer = &pjsua_call_on_rx_offer;
178 inv_cb.on_create_offer = &pjsua_call_on_create_offer;
179 inv_cb.on_tsx_state_changed = &pjsua_call_on_tsx_state_changed;
180 inv_cb.on_redirected = &pjsua_call_on_redirected;
181
182 /* Initialize invite session module: */
183 status = pjsip_inv_usage_init(pjsua_var.endpt, &inv_cb);
184 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
185
186 /* Add "norefersub" in Supported header */
187 pjsip_endpt_add_capability(pjsua_var.endpt, NULL, PJSIP_H_SUPPORTED,
188 NULL, 1, &str_norefersub);
189
190 /* Add "INFO" in Allow header, for DTMF and video key frame request. */
191 pjsip_endpt_add_capability(pjsua_var.endpt, NULL, PJSIP_H_ALLOW,
192 NULL, 1, &pjsip_info_method.name);
193
194 return status;
195}
196
197
198/*
199 * Start call subsystem.
200 */
201pj_status_t pjsua_call_subsys_start(void)
202{
203 /* Nothing to do */
204 return PJ_SUCCESS;
205}
206
207
208/*
209 * Get maximum number of calls configured in pjsua.
210 */
211PJ_DEF(unsigned) pjsua_call_get_max_count(void)
212{
213 return pjsua_var.ua_cfg.max_calls;
214}
215
216
217/*
218 * Get number of currently active calls.
219 */
220PJ_DEF(unsigned) pjsua_call_get_count(void)
221{
222 return pjsua_var.call_cnt;
223}
224
225
226/*
227 * Enum calls.
228 */
229PJ_DEF(pj_status_t) pjsua_enum_calls( pjsua_call_id ids[],
230 unsigned *count)
231{
232 unsigned i, c;
233
234 PJ_ASSERT_RETURN(ids && *count, PJ_EINVAL);
235
236 PJSUA_LOCK();
237
238 for (i=0, c=0; c<*count && i<pjsua_var.ua_cfg.max_calls; ++i) {
239 if (!pjsua_var.calls[i].inv)
240 continue;
241 ids[c] = i;
242 ++c;
243 }
244
245 *count = c;
246
247 PJSUA_UNLOCK();
248
249 return PJ_SUCCESS;
250}
251
252
253/* Allocate one call id */
254static pjsua_call_id alloc_call_id(void)
255{
256 pjsua_call_id cid;
257
258#if 1
259 /* New algorithm: round-robin */
260 if (pjsua_var.next_call_id >= (int)pjsua_var.ua_cfg.max_calls ||
261 pjsua_var.next_call_id < 0)
262 {
263 pjsua_var.next_call_id = 0;
264 }
265
266 for (cid=pjsua_var.next_call_id;
267 cid<(int)pjsua_var.ua_cfg.max_calls;
268 ++cid)
269 {
270 if (pjsua_var.calls[cid].inv == NULL &&
271 pjsua_var.calls[cid].async_call.dlg == NULL)
272 {
273 ++pjsua_var.next_call_id;
274 return cid;
275 }
276 }
277
278 for (cid=0; cid < pjsua_var.next_call_id; ++cid) {
279 if (pjsua_var.calls[cid].inv == NULL &&
280 pjsua_var.calls[cid].async_call.dlg == NULL)
281 {
282 ++pjsua_var.next_call_id;
283 return cid;
284 }
285 }
286
287#else
288 /* Old algorithm */
289 for (cid=0; cid<(int)pjsua_var.ua_cfg.max_calls; ++cid) {
290 if (pjsua_var.calls[cid].inv == NULL)
291 return cid;
292 }
293#endif
294
295 return PJSUA_INVALID_ID;
296}
297
298/* Get signaling secure level.
299 * Return:
300 * 0: if signaling is not secure
301 * 1: if TLS transport is used for immediate hop
302 * 2: if end-to-end signaling is secure.
303 */
304static int get_secure_level(pjsua_acc_id acc_id, const pj_str_t *dst_uri)
305{
306 const pj_str_t tls = pj_str(";transport=tls");
307 const pj_str_t sips = pj_str("sips:");
308 pjsua_acc *acc = &pjsua_var.acc[acc_id];
309
310 if (pj_stristr(dst_uri, &sips))
311 return 2;
312
313 if (!pj_list_empty(&acc->route_set)) {
314 pjsip_route_hdr *r = acc->route_set.next;
315 pjsip_uri *uri = r->name_addr.uri;
316 pjsip_sip_uri *sip_uri;
317
318 sip_uri = (pjsip_sip_uri*)pjsip_uri_get_uri(uri);
319 if (pj_stricmp2(&sip_uri->transport_param, "tls")==0)
320 return 1;
321
322 } else {
323 if (pj_stristr(dst_uri, &tls))
324 return 1;
325 }
326
327 return 0;
328}
329
330/*
331static int call_get_secure_level(pjsua_call *call)
332{
333 if (call->inv->dlg->secure)
334 return 2;
335
336 if (!pj_list_empty(&call->inv->dlg->route_set)) {
337 pjsip_route_hdr *r = call->inv->dlg->route_set.next;
338 pjsip_uri *uri = r->name_addr.uri;
339 pjsip_sip_uri *sip_uri;
340
341 sip_uri = (pjsip_sip_uri*)pjsip_uri_get_uri(uri);
342 if (pj_stricmp2(&sip_uri->transport_param, "tls")==0)
343 return 1;
344
345 } else {
346 pjsip_sip_uri *sip_uri;
347
348 if (PJSIP_URI_SCHEME_IS_SIPS(call->inv->dlg->target))
349 return 2;
350 if (!PJSIP_URI_SCHEME_IS_SIP(call->inv->dlg->target))
351 return 0;
352
353 sip_uri = (pjsip_sip_uri*) pjsip_uri_get_uri(call->inv->dlg->target);
354 if (pj_stricmp2(&sip_uri->transport_param, "tls")==0)
355 return 1;
356 }
357
358 return 0;
359}
360*/
361
362/* Outgoing call callback when media transport creation is completed. */
363static pj_status_t
364on_make_call_med_tp_complete(pjsua_call_id call_id,
365 const pjsua_med_tp_state_info *info)
366{
367 pjmedia_sdp_session *offer;
368 pjsip_inv_session *inv = NULL;
369 pjsua_call *call = &pjsua_var.calls[call_id];
370 pjsua_acc *acc = &pjsua_var.acc[call->acc_id];
371 pjsip_dialog *dlg = call->async_call.dlg;
372 unsigned options = 0;
373 pjsip_tx_data *tdata;
374 pj_bool_t cb_called = PJ_FALSE;
375 pj_status_t status = (info? info->status: PJ_SUCCESS);
376
377 PJSUA_LOCK();
378
379 /* Increment the dialog's lock otherwise when invite session creation
380 * fails the dialog will be destroyed prematurely.
381 */
382 pjsip_dlg_inc_lock(dlg);
383
384 /* Decrement dialog session. */
385 pjsip_dlg_dec_session(dlg, &pjsua_var.mod);
386
387 if (status != PJ_SUCCESS) {
388 pj_str_t err_str;
389 pj_ssize_t title_len;
390
391 call->last_code = PJSIP_SC_TEMPORARILY_UNAVAILABLE;
392 pj_strcpy2(&call->last_text, "Media init error: ");
393
394 title_len = call->last_text.slen;
395 err_str = pj_strerror(status, call->last_text_buf_ + title_len,
396 sizeof(call->last_text_buf_) - title_len);
397 call->last_text.slen += err_str.slen;
398
399 pjsua_perror(THIS_FILE, "Error initializing media channel", status);
400 goto on_error;
401 }
402
403 /* pjsua_media_channel_deinit() has been called or
404 * call has been hung up.
405 */
406 if (call->async_call.med_ch_deinit ||
407 call->async_call.call_var.out_call.hangup)
408 {
409 PJ_LOG(4,(THIS_FILE, "Call has been hung up or media channel has "
410 "been deinitialized"));
411 goto on_error;
412 }
413
414 /* Create offer */
415 status = pjsua_media_channel_create_sdp(call->index, dlg->pool, NULL,
416 &offer, NULL);
417 if (status != PJ_SUCCESS) {
418 pjsua_perror(THIS_FILE, "Error initializing media channel", status);
419 goto on_error;
420 }
421
422 /* Create the INVITE session: */
423 options |= PJSIP_INV_SUPPORT_100REL;
424 if (acc->cfg.require_100rel)
425 options |= PJSIP_INV_REQUIRE_100REL;
426 if (acc->cfg.use_timer != PJSUA_SIP_TIMER_INACTIVE) {
427 options |= PJSIP_INV_SUPPORT_TIMER;
428 if (acc->cfg.use_timer == PJSUA_SIP_TIMER_REQUIRED)
429 options |= PJSIP_INV_REQUIRE_TIMER;
430 else if (acc->cfg.use_timer == PJSUA_SIP_TIMER_ALWAYS)
431 options |= PJSIP_INV_ALWAYS_USE_TIMER;
432 }
433
434 status = pjsip_inv_create_uac( dlg, offer, options, &inv);
435 if (status != PJ_SUCCESS) {
436 pjsua_perror(THIS_FILE, "Invite session creation failed", status);
437 goto on_error;
438 }
439
440 /* Init Session Timers */
441 status = pjsip_timer_init_session(inv, &acc->cfg.timer_setting);
442 if (status != PJ_SUCCESS) {
443 pjsua_perror(THIS_FILE, "Session Timer init failed", status);
444 goto on_error;
445 }
446
447 /* Create and associate our data in the session. */
448 call->inv = inv;
449
450 dlg->mod_data[pjsua_var.mod.id] = call;
451 inv->mod_data[pjsua_var.mod.id] = call;
452
453 /* If account is locked to specific transport, then lock dialog
454 * to this transport too.
455 */
456 if (acc->cfg.transport_id != PJSUA_INVALID_ID) {
457 pjsip_tpselector tp_sel;
458
459 pjsua_init_tpselector(acc->cfg.transport_id, &tp_sel);
460 pjsip_dlg_set_transport(dlg, &tp_sel);
461 }
462
463 /* Set dialog Route-Set: */
464 if (!pj_list_empty(&acc->route_set))
465 pjsip_dlg_set_route_set(dlg, &acc->route_set);
466
467
468 /* Set credentials: */
469 if (acc->cred_cnt) {
470 pjsip_auth_clt_set_credentials( &dlg->auth_sess,
471 acc->cred_cnt, acc->cred);
472 }
473
474 /* Set authentication preference */
475 pjsip_auth_clt_set_prefs(&dlg->auth_sess, &acc->cfg.auth_pref);
476
477 /* Create initial INVITE: */
478
479 status = pjsip_inv_invite(inv, &tdata);
480 if (status != PJ_SUCCESS) {
481 pjsua_perror(THIS_FILE, "Unable to create initial INVITE request",
482 status);
483 goto on_error;
484 }
485
486
487 /* Add additional headers etc */
488
489 pjsua_process_msg_data( tdata,
490 call->async_call.call_var.out_call.msg_data);
491
492 /* Must increment call counter now */
493 ++pjsua_var.call_cnt;
494
495 /* Send initial INVITE: */
496
497 status = pjsip_inv_send_msg(inv, tdata);
498 if (status != PJ_SUCCESS) {
499 cb_called = PJ_TRUE;
500
501 /* Upon failure to send first request, the invite
502 * session would have been cleared.
503 */
504 inv = NULL;
505 goto on_error;
506 }
507
508 /* Done. */
509 call->med_ch_cb = NULL;
510
511 pjsip_dlg_dec_lock(dlg);
512 PJSUA_UNLOCK();
513
514 return PJ_SUCCESS;
515
516on_error:
517 if (inv == NULL && call_id != -1 && !cb_called &&
518 pjsua_var.ua_cfg.cb.on_call_state)
519 {
520 (*pjsua_var.ua_cfg.cb.on_call_state)(call_id, NULL);
521 }
522
523 if (dlg) {
524 /* This may destroy the dialog */
525 pjsip_dlg_dec_lock(dlg);
526 }
527
528 if (inv != NULL) {
529 pjsip_inv_terminate(inv, PJSIP_SC_OK, PJ_FALSE);
530 }
531
532 if (call_id != -1) {
533 pjsua_media_channel_deinit(call_id);
534 reset_call(call_id);
535 }
536
537 call->med_ch_cb = NULL;
538
539 pjsua_check_snd_dev_idle();
540
541 PJSUA_UNLOCK();
542 return status;
543}
544
545
546/*
547 * Initialize call settings based on account ID.
548 */
549PJ_DEF(void) pjsua_call_setting_default(pjsua_call_setting *opt)
550{
551 pj_assert(opt);
552
553 pj_bzero(opt, sizeof(*opt));
554 opt->flag = PJSUA_CALL_INCLUDE_DISABLED_MEDIA;
555 opt->aud_cnt = 1;
556
557#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
558 opt->vid_cnt = 1;
559 opt->req_keyframe_method = PJSUA_VID_REQ_KEYFRAME_SIP_INFO |
560 PJSUA_VID_REQ_KEYFRAME_RTCP_PLI;
561#endif
562}
563
564static pj_status_t apply_call_setting(pjsua_call *call,
565 const pjsua_call_setting *opt,
566 const pjmedia_sdp_session *rem_sdp)
567{
568 pj_assert(call);
569
570 if (!opt)
571 return PJ_SUCCESS;
572
573#if !PJMEDIA_HAS_VIDEO
574 pj_assert(opt->vid_cnt == 0);
575#endif
576
577 call->opt = *opt;
578
579 /* If call is established, reinit media channel */
580 if (call->inv && call->inv->state == PJSIP_INV_STATE_CONFIRMED) {
581 pjsip_role_e role = rem_sdp? PJSIP_ROLE_UAS : PJSIP_ROLE_UAC;
582 pj_status_t status;
583
584 status = pjsua_media_channel_init(call->index, role,
585 call->secure_level,
586 call->inv->pool_prov,
587 rem_sdp, NULL,
588 PJ_FALSE, NULL);
589 if (status != PJ_SUCCESS) {
590 pjsua_perror(THIS_FILE, "Error re-initializing media channel",
591 status);
592 return status;
593 }
594 }
595
596 return PJ_SUCCESS;
597}
598
599/*
600 * Make outgoing call to the specified URI using the specified account.
601 */
602PJ_DEF(pj_status_t) pjsua_call_make_call(pjsua_acc_id acc_id,
603 const pj_str_t *dest_uri,
604 const pjsua_call_setting *opt,
605 void *user_data,
606 const pjsua_msg_data *msg_data,
607 pjsua_call_id *p_call_id)
608{
609 pj_pool_t *tmp_pool = NULL;
610 pjsip_dialog *dlg = NULL;
611 pjsua_acc *acc;
612 pjsua_call *call;
613 int call_id = -1;
614 pj_str_t contact;
615 pj_status_t status;
616
617
618 /* Check that account is valid */
619 PJ_ASSERT_RETURN(acc_id>=0 || acc_id<(int)PJ_ARRAY_SIZE(pjsua_var.acc),
620 PJ_EINVAL);
621
622 /* Check arguments */
623 PJ_ASSERT_RETURN(dest_uri, PJ_EINVAL);
624
625 PJ_LOG(4,(THIS_FILE, "Making call with acc #%d to %.*s", acc_id,
626 (int)dest_uri->slen, dest_uri->ptr));
627
628 pj_log_push_indent();
629
630 PJSUA_LOCK();
631
632 /* Create sound port if none is instantiated, to check if sound device
633 * can be used. But only do this with the conference bridge, as with
634 * audio switchboard (i.e. APS-Direct), we can only open the sound
635 * device once the correct format has been known
636 */
637 if (!pjsua_var.is_mswitch && pjsua_var.snd_port==NULL &&
638 pjsua_var.null_snd==NULL && !pjsua_var.no_snd)
639 {
640 status = pjsua_set_snd_dev(pjsua_var.cap_dev, pjsua_var.play_dev);
641 if (status != PJ_SUCCESS)
642 goto on_error;
643 }
644
645 acc = &pjsua_var.acc[acc_id];
646 if (!acc->valid) {
647 pjsua_perror(THIS_FILE, "Unable to make call because account "
648 "is not valid", PJ_EINVALIDOP);
649 status = PJ_EINVALIDOP;
650 goto on_error;
651 }
652
653 /* Find free call slot. */
654 call_id = alloc_call_id();
655
656 if (call_id == PJSUA_INVALID_ID) {
657 pjsua_perror(THIS_FILE, "Error making call", PJ_ETOOMANY);
658 status = PJ_ETOOMANY;
659 goto on_error;
660 }
661
662 /* Clear call descriptor */
663 reset_call(call_id);
664
665 call = &pjsua_var.calls[call_id];
666
667 /* Associate session with account */
668 call->acc_id = acc_id;
669 call->call_hold_type = acc->cfg.call_hold_type;
670
671 /* Apply call setting */
672 status = apply_call_setting(call, opt, NULL);
673 if (status != PJ_SUCCESS) {
674 pjsua_perror(THIS_FILE, "Failed to apply call setting", status);
675 goto on_error;
676 }
677
678 /* Create temporary pool */
679 tmp_pool = pjsua_pool_create("tmpcall10", 512, 256);
680
681 /* Verify that destination URI is valid before calling
682 * pjsua_acc_create_uac_contact, or otherwise there
683 * a misleading "Invalid Contact URI" error will be printed
684 * when pjsua_acc_create_uac_contact() fails.
685 */
686 if (1) {
687 pjsip_uri *uri;
688 pj_str_t dup;
689
690 pj_strdup_with_null(tmp_pool, &dup, dest_uri);
691 uri = pjsip_parse_uri(tmp_pool, dup.ptr, dup.slen, 0);
692
693 if (uri == NULL) {
694 pjsua_perror(THIS_FILE, "Unable to make call",
695 PJSIP_EINVALIDREQURI);
696 status = PJSIP_EINVALIDREQURI;
697 goto on_error;
698 }
699 }
700
701 /* Mark call start time. */
702 pj_gettimeofday(&call->start_time);
703
704 /* Reset first response time */
705 call->res_time.sec = 0;
706
707 /* Create suitable Contact header unless a Contact header has been
708 * set in the account.
709 */
710 if (acc->contact.slen) {
711 contact = acc->contact;
712 } else {
713 status = pjsua_acc_create_uac_contact(tmp_pool, &contact,
714 acc_id, dest_uri);
715 if (status != PJ_SUCCESS) {
716 pjsua_perror(THIS_FILE, "Unable to generate Contact header",
717 status);
718 goto on_error;
719 }
720 }
721
722 /* Create outgoing dialog: */
723 status = pjsip_dlg_create_uac( pjsip_ua_instance(),
724 &acc->cfg.id, &contact,
725 dest_uri,
726 (msg_data && msg_data->target_uri.slen?
727 &msg_data->target_uri: dest_uri),
728 &dlg);
729 if (status != PJ_SUCCESS) {
730 pjsua_perror(THIS_FILE, "Dialog creation failed", status);
731 goto on_error;
732 }
733
734 /* Increment the dialog's lock otherwise when invite session creation
735 * fails the dialog will be destroyed prematurely.
736 */
737 pjsip_dlg_inc_lock(dlg);
738
739 if (acc->cfg.allow_via_rewrite && acc->via_addr.host.slen > 0)
740 pjsip_dlg_set_via_sent_by(dlg, &acc->via_addr, acc->via_tp);
741
742 /* Calculate call's secure level */
743 call->secure_level = get_secure_level(acc_id, dest_uri);
744
745 /* Attach user data */
746 call->user_data = user_data;
747
748 /* Store variables required for the callback after the async
749 * media transport creation is completed.
750 */
751 if (msg_data) {
752 call->async_call.call_var.out_call.msg_data = pjsua_msg_data_clone(
753 dlg->pool, msg_data);
754 }
755 call->async_call.dlg = dlg;
756
757 /* Temporarily increment dialog session. Without this, dialog will be
758 * prematurely destroyed if dec_lock() is called on the dialog before
759 * the invite session is created.
760 */
761 pjsip_dlg_inc_session(dlg, &pjsua_var.mod);
762
763 /* Init media channel */
764 status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAC,
765 call->secure_level, dlg->pool,
766 NULL, NULL, PJ_TRUE,
767 &on_make_call_med_tp_complete);
768 if (status == PJ_SUCCESS) {
769 status = on_make_call_med_tp_complete(call->index, NULL);
770 if (status != PJ_SUCCESS)
771 goto on_error;
772 } else if (status != PJ_EPENDING) {
773 pjsua_perror(THIS_FILE, "Error initializing media channel", status);
774 pjsip_dlg_dec_session(dlg, &pjsua_var.mod);
775 goto on_error;
776 }
777
778 /* Done. */
779
780 if (p_call_id)
781 *p_call_id = call_id;
782
783 pjsip_dlg_dec_lock(dlg);
784 pj_pool_release(tmp_pool);
785 PJSUA_UNLOCK();
786
787 pj_log_pop_indent();
788
789 return PJ_SUCCESS;
790
791
792on_error:
793 if (dlg) {
794 /* This may destroy the dialog */
795 pjsip_dlg_dec_lock(dlg);
796 }
797
798 if (call_id != -1) {
799 pjsua_media_channel_deinit(call_id);
800 reset_call(call_id);
801 }
802
803 pjsua_check_snd_dev_idle();
804
805 if (tmp_pool)
806 pj_pool_release(tmp_pool);
807 PJSUA_UNLOCK();
808
809 pj_log_pop_indent();
810 return status;
811}
812
813
814/* Get the NAT type information in remote's SDP */
815static void update_remote_nat_type(pjsua_call *call,
816 const pjmedia_sdp_session *sdp)
817{
818 const pjmedia_sdp_attr *xnat;
819
820 xnat = pjmedia_sdp_attr_find2(sdp->attr_count, sdp->attr, "X-nat", NULL);
821 if (xnat) {
822 call->rem_nat_type = (pj_stun_nat_type) (xnat->value.ptr[0] - '0');
823 } else {
824 call->rem_nat_type = PJ_STUN_NAT_TYPE_UNKNOWN;
825 }
826
827 PJ_LOG(5,(THIS_FILE, "Call %d: remote NAT type is %d (%s)", call->index,
828 call->rem_nat_type, pj_stun_get_nat_name(call->rem_nat_type)));
829}
830
831
832static pj_status_t process_incoming_call_replace(pjsua_call *call,
833 pjsip_dialog *replaced_dlg)
834{
835 pjsip_inv_session *replaced_inv;
836 struct pjsua_call *replaced_call;
837 pjsip_tx_data *tdata = NULL;
838 pj_status_t status = PJ_SUCCESS;
839
840 /* Get the invite session in the dialog */
841 replaced_inv = pjsip_dlg_get_inv_session(replaced_dlg);
842
843 /* Get the replaced call instance */
844 replaced_call = (pjsua_call*) replaced_dlg->mod_data[pjsua_var.mod.id];
845
846 /* Notify application */
847 if (pjsua_var.ua_cfg.cb.on_call_replaced)
848 pjsua_var.ua_cfg.cb.on_call_replaced(replaced_call->index,
849 call->index);
850
851 if (replaced_call->inv->state <= PJSIP_INV_STATE_EARLY &&
852 replaced_call->inv->role != PJSIP_ROLE_UAC)
853 {
854 if (replaced_call->last_code > 100 && replaced_call->last_code < 200)
855 {
856 pjsip_status_code code = replaced_call->last_code;
857 pj_str_t *text = &replaced_call->last_text;
858
859 PJ_LOG(4,(THIS_FILE, "Answering replacement call %d with %d/%.*s",
860 call->index, code, text->slen, text->ptr));
861
862 /* Answer the new call with last response in the replaced call */
863 status = pjsip_inv_answer(call->inv, code, text, NULL, &tdata);
864 }
865 } else {
866 PJ_LOG(4,(THIS_FILE, "Answering replacement call %d with 200/OK",
867 call->index));
868
869 /* Answer the new call with 200 response */
870 status = pjsip_inv_answer(call->inv, 200, NULL, NULL, &tdata);
871 }
872
873 if (status == PJ_SUCCESS && tdata)
874 status = pjsip_inv_send_msg(call->inv, tdata);
875
876 if (status != PJ_SUCCESS)
877 pjsua_perror(THIS_FILE, "Error answering session", status);
878
879 /* Note that inv may be invalid if 200/OK has caused error in
880 * starting the media.
881 */
882
883 PJ_LOG(4,(THIS_FILE, "Disconnecting replaced call %d",
884 replaced_call->index));
885
886 /* Disconnect replaced invite session */
887 status = pjsip_inv_end_session(replaced_inv, PJSIP_SC_GONE, NULL,
888 &tdata);
889 if (status == PJ_SUCCESS && tdata)
890 status = pjsip_inv_send_msg(replaced_inv, tdata);
891
892 if (status != PJ_SUCCESS)
893 pjsua_perror(THIS_FILE, "Error terminating session", status);
894
895 return status;
896}
897
898
899static void process_pending_call_answer(pjsua_call *call)
900{
901 struct call_answer *answer, *next;
902
903 answer = call->async_call.call_var.inc_call.answers.next;
904 while (answer != &call->async_call.call_var.inc_call.answers) {
905 next = answer->next;
906 pjsua_call_answer2(call->index, answer->opt, answer->code,
907 answer->reason, answer->msg_data);
908
909 /* Call might have been disconnected if application is answering
910 * with 200/OK and the media failed to start.
911 * See pjsua_call_answer() below.
912 */
913 if (!call->inv || !call->inv->pool_prov)
914 break;
915
916 pj_list_erase(answer);
917 answer = next;
918 }
919}
920
921
922/* Incoming call callback when media transport creation is completed. */
923static pj_status_t
924on_incoming_call_med_tp_complete(pjsua_call_id call_id,
925 const pjsua_med_tp_state_info *info)
926{
927 pjsua_call *call = &pjsua_var.calls[call_id];
928 const pjmedia_sdp_session *offer=NULL;
929 pjmedia_sdp_session *answer;
930 pjsip_tx_data *response = NULL;
931 unsigned options = 0;
932 int sip_err_code = (info? info->sip_err_code: 0);
933 pj_status_t status = (info? info->status: PJ_SUCCESS);
934
935 PJSUA_LOCK();
936
937 if (status != PJ_SUCCESS) {
938 pjsua_perror(THIS_FILE, "Error initializing media channel", status);
939 goto on_return;
940 }
941
942 /* pjsua_media_channel_deinit() has been called. */
943 if (call->async_call.med_ch_deinit) {
944 pjsua_media_channel_deinit(call->index);
945 call->med_ch_cb = NULL;
946 PJSUA_UNLOCK();
947 return PJ_SUCCESS;
948 }
949
950 /* Get remote SDP offer (if any). */
951 if (call->inv->neg)
952 pjmedia_sdp_neg_get_neg_remote(call->inv->neg, &offer);
953
954 status = pjsua_media_channel_create_sdp(call_id,
955 call->async_call.dlg->pool,
956 offer, &answer, &sip_err_code);
957 if (status != PJ_SUCCESS) {
958 pjsua_perror(THIS_FILE, "Error creating SDP answer", status);
959 goto on_return;
960 }
961
962 status = pjsip_inv_set_local_sdp(call->inv, answer);
963 if (status != PJ_SUCCESS) {
964 pjsua_perror(THIS_FILE, "Error setting local SDP", status);
965 sip_err_code = PJSIP_SC_NOT_ACCEPTABLE_HERE;
966 goto on_return;
967 }
968
969 /* Verify that we can handle the request. */
970 status = pjsip_inv_verify_request3(NULL,
971 call->inv->pool_prov, &options, offer,
972 answer, NULL, pjsua_var.endpt, &response);
973 if (status != PJ_SUCCESS) {
974 /*
975 * No we can't handle the incoming INVITE request.
976 */
977 sip_err_code = PJSIP_ERRNO_TO_SIP_STATUS(status);
978 goto on_return;
979 }
980
981on_return:
982 if (status != PJ_SUCCESS) {
983 /* If the callback is called from pjsua_call_on_incoming(), the
984 * invite's state is PJSIP_INV_STATE_NULL, so the invite session
985 * will be terminated later, otherwise we end the session here.
986 */
987 if (call->inv->state > PJSIP_INV_STATE_NULL) {
988 pjsip_tx_data *tdata;
989 pj_status_t status_;
990
991 status_ = pjsip_inv_end_session(call->inv, sip_err_code, NULL,
992 &tdata);
993 if (status_ == PJ_SUCCESS && tdata)
994 status_ = pjsip_inv_send_msg(call->inv, tdata);
995 }
996
997 pjsua_media_channel_deinit(call->index);
998 }
999
1000 /* Set the callback to NULL to indicate that the async operation
1001 * has completed.
1002 */
1003 call->med_ch_cb = NULL;
1004
1005 /* Finish any pending process */
1006 if (status == PJ_SUCCESS) {
1007 if (call->async_call.call_var.inc_call.replaced_dlg) {
1008 /* Process pending call replace */
1009 pjsip_dialog *replaced_dlg =
1010 call->async_call.call_var.inc_call.replaced_dlg;
1011 process_incoming_call_replace(call, replaced_dlg);
1012 } else {
1013 /* Process pending call answers */
1014 process_pending_call_answer(call);
1015 }
1016 }
1017
1018 PJSUA_UNLOCK();
1019 return status;
1020}
1021
1022
1023/**
1024 * Handle incoming INVITE request.
1025 * Called by pjsua_core.c
1026 */
1027pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
1028{
1029 pj_str_t contact;
1030 pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata);
1031 pjsip_dialog *replaced_dlg = NULL;
1032 pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
1033 pjsip_msg *msg = rdata->msg_info.msg;
1034 pjsip_tx_data *response = NULL;
1035 unsigned options = 0;
1036 pjsip_inv_session *inv = NULL;
1037 int acc_id;
1038 pjsua_call *call;
1039 int call_id = -1;
1040 int sip_err_code = PJSIP_SC_INTERNAL_SERVER_ERROR;
1041 pjmedia_sdp_session *offer=NULL;
1042 pj_status_t status;
1043
1044 /* Don't want to handle anything but INVITE */
1045 if (msg->line.req.method.id != PJSIP_INVITE_METHOD)
1046 return PJ_FALSE;
1047
1048 /* Don't want to handle anything that's already associated with
1049 * existing dialog or transaction.
1050 */
1051 if (dlg || tsx)
1052 return PJ_FALSE;
1053
1054 /* Don't want to accept the call if shutdown is in progress */
1055 if (pjsua_var.thread_quit_flag) {
1056 pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata,
1057 PJSIP_SC_TEMPORARILY_UNAVAILABLE, NULL,
1058 NULL, NULL);
1059 return PJ_TRUE;
1060 }
1061
1062 PJ_LOG(4,(THIS_FILE, "Incoming %s", rdata->msg_info.info));
1063 pj_log_push_indent();
1064
1065 PJSUA_LOCK();
1066
1067 /* Find free call slot. */
1068 call_id = alloc_call_id();
1069
1070 if (call_id == PJSUA_INVALID_ID) {
1071 pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata,
1072 PJSIP_SC_BUSY_HERE, NULL,
1073 NULL, NULL);
1074 PJ_LOG(2,(THIS_FILE,
1075 "Unable to accept incoming call (too many calls)"));
1076 goto on_return;
1077 }
1078
1079 /* Clear call descriptor */
1080 reset_call(call_id);
1081
1082 call = &pjsua_var.calls[call_id];
1083
1084 /* Mark call start time. */
1085 pj_gettimeofday(&call->start_time);
1086
1087 /* Check INVITE request for Replaces header. If Replaces header is
1088 * present, the function will make sure that we can handle the request.
1089 */
1090 status = pjsip_replaces_verify_request(rdata, &replaced_dlg, PJ_FALSE,
1091 &response);
1092 if (status != PJ_SUCCESS) {
1093 /*
1094 * Something wrong with the Replaces header.
1095 */
1096 if (response) {
1097 pjsip_response_addr res_addr;
1098
1099 pjsip_get_response_addr(response->pool, rdata, &res_addr);
1100 pjsip_endpt_send_response(pjsua_var.endpt, &res_addr, response,
1101 NULL, NULL);
1102
1103 } else {
1104
1105 /* Respond with 500 (Internal Server Error) */
1106 pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 500, NULL,
1107 NULL, NULL);
1108 }
1109
1110 goto on_return;
1111 }
1112
1113 /* If this INVITE request contains Replaces header, notify application
1114 * about the request so that application can do subsequent checking
1115 * if it wants to.
1116 */
1117 if (replaced_dlg != NULL &&
1118 (pjsua_var.ua_cfg.cb.on_call_replace_request ||
1119 pjsua_var.ua_cfg.cb.on_call_replace_request2))
1120 {
1121 pjsua_call *replaced_call;
1122 int st_code = 200;
1123 pj_str_t st_text = { "OK", 2 };
1124
1125 /* Get the replaced call instance */
1126 replaced_call = (pjsua_call*) replaced_dlg->mod_data[pjsua_var.mod.id];
1127
1128 /* Copy call setting from the replaced call */
1129 call->opt = replaced_call->opt;
1130
1131 /* Notify application */
1132 if (pjsua_var.ua_cfg.cb.on_call_replace_request) {
1133 pjsua_var.ua_cfg.cb.on_call_replace_request(replaced_call->index,
1134 rdata,
1135 &st_code, &st_text);
1136 }
1137
1138 if (pjsua_var.ua_cfg.cb.on_call_replace_request2) {
1139 pjsua_var.ua_cfg.cb.on_call_replace_request2(replaced_call->index,
1140 rdata,
1141 &st_code, &st_text,
1142 &call->opt);
1143 }
1144
1145 /* Must specify final response */
1146 PJ_ASSERT_ON_FAIL(st_code >= 200, st_code = 200);
1147
1148 /* Check if application rejects this request. */
1149 if (st_code >= 300) {
1150
1151 if (st_text.slen == 2)
1152 st_text = *pjsip_get_status_text(st_code);
1153
1154 pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata,
1155 st_code, &st_text, NULL, NULL, NULL);
1156 goto on_return;
1157 }
1158 }
1159
1160 /*
1161 * Get which account is most likely to be associated with this incoming
1162 * call. We need the account to find which contact URI to put for
1163 * the call.
1164 */
1165 acc_id = call->acc_id = pjsua_acc_find_for_incoming(rdata);
1166 call->call_hold_type = pjsua_var.acc[acc_id].cfg.call_hold_type;
1167
1168 /* Get call's secure level */
1169 if (PJSIP_URI_SCHEME_IS_SIPS(rdata->msg_info.msg->line.req.uri))
1170 call->secure_level = 2;
1171 else if (PJSIP_TRANSPORT_IS_SECURE(rdata->tp_info.transport))
1172 call->secure_level = 1;
1173 else
1174 call->secure_level = 0;
1175
1176 /* Parse SDP from incoming request */
1177 if (rdata->msg_info.msg->body) {
1178 pjsip_rdata_sdp_info *sdp_info;
1179
1180 sdp_info = pjsip_rdata_get_sdp_info(rdata);
1181 offer = sdp_info->sdp;
1182
1183 status = sdp_info->sdp_err;
1184 if (status==PJ_SUCCESS && sdp_info->sdp==NULL)
1185 status = PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_NOT_ACCEPTABLE);
1186
1187 if (status != PJ_SUCCESS) {
1188 const pj_str_t reason = pj_str("Bad SDP");
1189 pjsip_hdr hdr_list;
1190 pjsip_warning_hdr *w;
1191
1192 pjsua_perror(THIS_FILE, "Bad SDP in incoming INVITE",
1193 status);
1194
1195 w = pjsip_warning_hdr_create_from_status(rdata->tp_info.pool,
1196 pjsip_endpt_name(pjsua_var.endpt),
1197 status);
1198 pj_list_init(&hdr_list);
1199 pj_list_push_back(&hdr_list, w);
1200
1201 pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata, 400,
1202 &reason, &hdr_list, NULL, NULL);
1203 goto on_return;
1204 }
1205
1206 /* Do quick checks on SDP before passing it to transports. More elabore
1207 * checks will be done in pjsip_inv_verify_request2() below.
1208 */
1209 if (offer->media_count==0) {
1210 const pj_str_t reason = pj_str("Missing media in SDP");
1211 pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata, 400, &reason,
1212 NULL, NULL, NULL);
1213 goto on_return;
1214 }
1215
1216 } else {
1217 offer = NULL;
1218 }
1219
1220 /* Verify that we can handle the request. */
1221 options |= PJSIP_INV_SUPPORT_100REL;
1222 options |= PJSIP_INV_SUPPORT_TIMER;
1223 if (pjsua_var.acc[acc_id].cfg.require_100rel == PJSUA_100REL_MANDATORY)
1224 options |= PJSIP_INV_REQUIRE_100REL;
1225 if (pjsua_var.acc[acc_id].cfg.ice_cfg.enable_ice)
1226 options |= PJSIP_INV_SUPPORT_ICE;
1227 if (pjsua_var.acc[acc_id].cfg.use_timer == PJSUA_SIP_TIMER_REQUIRED)
1228 options |= PJSIP_INV_REQUIRE_TIMER;
1229 else if (pjsua_var.acc[acc_id].cfg.use_timer == PJSUA_SIP_TIMER_ALWAYS)
1230 options |= PJSIP_INV_ALWAYS_USE_TIMER;
1231
1232 status = pjsip_inv_verify_request2(rdata, &options, offer, NULL, NULL,
1233 pjsua_var.endpt, &response);
1234 if (status != PJ_SUCCESS) {
1235
1236 /*
1237 * No we can't handle the incoming INVITE request.
1238 */
1239 if (response) {
1240 pjsip_response_addr res_addr;
1241
1242 pjsip_get_response_addr(response->pool, rdata, &res_addr);
1243 pjsip_endpt_send_response(pjsua_var.endpt, &res_addr, response,
1244 NULL, NULL);
1245
1246 } else {
1247 /* Respond with 500 (Internal Server Error) */
1248 pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata, 500, NULL,
1249 NULL, NULL, NULL);
1250 }
1251
1252 goto on_return;
1253 }
1254
1255 /* Get suitable Contact header */
1256 if (pjsua_var.acc[acc_id].contact.slen) {
1257 contact = pjsua_var.acc[acc_id].contact;
1258 } else {
1259 status = pjsua_acc_create_uas_contact(rdata->tp_info.pool, &contact,
1260 acc_id, rdata);
1261 if (status != PJ_SUCCESS) {
1262 pjsua_perror(THIS_FILE, "Unable to generate Contact header",
1263 status);
1264 pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 500, NULL,
1265 NULL, NULL);
1266 goto on_return;
1267 }
1268 }
1269
1270 /* Create dialog: */
1271 status = pjsip_dlg_create_uas( pjsip_ua_instance(), rdata,
1272 &contact, &dlg);
1273 if (status != PJ_SUCCESS) {
1274 pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 500, NULL,
1275 NULL, NULL);
1276 goto on_return;
1277 }
1278
1279 if (pjsua_var.acc[acc_id].cfg.allow_via_rewrite &&
1280 pjsua_var.acc[acc_id].via_addr.host.slen > 0)
1281 {
1282 pjsip_dlg_set_via_sent_by(dlg, &pjsua_var.acc[acc_id].via_addr,
1283 pjsua_var.acc[acc_id].via_tp);
1284 }
1285
1286 /* Set credentials */
1287 if (pjsua_var.acc[acc_id].cred_cnt) {
1288 pjsip_auth_clt_set_credentials(&dlg->auth_sess,
1289 pjsua_var.acc[acc_id].cred_cnt,
1290 pjsua_var.acc[acc_id].cred);
1291 }
1292
1293 /* Set preference */
1294 pjsip_auth_clt_set_prefs(&dlg->auth_sess,
1295 &pjsua_var.acc[acc_id].cfg.auth_pref);
1296
1297 /* Disable Session Timers if not prefered and the incoming INVITE request
1298 * did not require it.
1299 */
1300 if (pjsua_var.acc[acc_id].cfg.use_timer == PJSUA_SIP_TIMER_INACTIVE &&
1301 (options & PJSIP_INV_REQUIRE_TIMER) == 0)
1302 {
1303 options &= ~(PJSIP_INV_SUPPORT_TIMER);
1304 }
1305
1306 /* If 100rel is optional and UAC supports it, use it. */
1307 if ((options & PJSIP_INV_REQUIRE_100REL)==0 &&
1308 pjsua_var.acc[acc_id].cfg.require_100rel == PJSUA_100REL_OPTIONAL)
1309 {
1310 const pj_str_t token = { "100rel", 6};
1311 pjsip_dialog_cap_status cap_status;
1312
1313 cap_status = pjsip_dlg_remote_has_cap(dlg, PJSIP_H_SUPPORTED, NULL,
1314 &token);
1315 if (cap_status == PJSIP_DIALOG_CAP_SUPPORTED)
1316 options |= PJSIP_INV_REQUIRE_100REL;
1317 }
1318
1319 /* Create invite session: */
1320 status = pjsip_inv_create_uas( dlg, rdata, NULL, options, &inv);
1321 if (status != PJ_SUCCESS) {
1322 pjsip_hdr hdr_list;
1323 pjsip_warning_hdr *w;
1324
1325 w = pjsip_warning_hdr_create_from_status(dlg->pool,
1326 pjsip_endpt_name(pjsua_var.endpt),
1327 status);
1328 pj_list_init(&hdr_list);
1329 pj_list_push_back(&hdr_list, w);
1330
1331 pjsip_dlg_respond(dlg, rdata, 500, NULL, &hdr_list, NULL);
1332
1333 /* Can't terminate dialog because transaction is in progress.
1334 pjsip_dlg_terminate(dlg);
1335 */
1336 goto on_return;
1337 }
1338
1339 /* If account is locked to specific transport, then lock dialog
1340 * to this transport too.
1341 */
1342 if (pjsua_var.acc[acc_id].cfg.transport_id != PJSUA_INVALID_ID) {
1343 pjsip_tpselector tp_sel;
1344
1345 pjsua_init_tpselector(pjsua_var.acc[acc_id].cfg.transport_id, &tp_sel);
1346 pjsip_dlg_set_transport(dlg, &tp_sel);
1347 }
1348
1349 /* Create and attach pjsua_var data to the dialog */
1350 call->inv = inv;
1351
1352 /* Store variables required for the callback after the async
1353 * media transport creation is completed.
1354 */
1355 call->async_call.dlg = dlg;
1356 pj_list_init(&call->async_call.call_var.inc_call.answers);
1357
1358 /* Init media channel, only when there is offer or call replace request.
1359 * For incoming call without SDP offer, media channel init will be done
1360 * in pjsua_call_answer(), see ticket #1526.
1361 */
1362 if (offer || replaced_dlg) {
1363 status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAS,
1364 call->secure_level,
1365 rdata->tp_info.pool,
1366 offer,
1367 &sip_err_code, PJ_TRUE,
1368 &on_incoming_call_med_tp_complete);
1369 if (status == PJ_SUCCESS) {
1370 status = on_incoming_call_med_tp_complete(call_id, NULL);
1371 if (status != PJ_SUCCESS) {
1372 sip_err_code = PJSIP_SC_NOT_ACCEPTABLE;
1373 /* Since the call invite's state is still PJSIP_INV_STATE_NULL,
1374 * the invite session was not ended in
1375 * on_incoming_call_med_tp_complete(), so we need to send
1376 * a response message and terminate the invite here.
1377 */
1378 pjsip_dlg_respond(dlg, rdata, sip_err_code, NULL, NULL, NULL);
1379 pjsip_inv_terminate(call->inv, sip_err_code, PJ_FALSE);
1380 call->inv = NULL;
1381 call->async_call.dlg = NULL;
1382 goto on_return;
1383 }
1384 } else if (status != PJ_EPENDING) {
1385 pjsua_perror(THIS_FILE, "Error initializing media channel", status);
1386 pjsip_dlg_respond(dlg, rdata, sip_err_code, NULL, NULL, NULL);
1387 pjsip_inv_terminate(call->inv, sip_err_code, PJ_FALSE);
1388 call->inv = NULL;
1389 call->async_call.dlg = NULL;
1390 goto on_return;
1391 }
1392 }
1393
1394 /* Create answer */
1395/*
1396 status = pjsua_media_channel_create_sdp(call->index, rdata->tp_info.pool,
1397 offer, &answer, &sip_err_code);
1398 if (status != PJ_SUCCESS) {
1399 pjsua_perror(THIS_FILE, "Error creating SDP answer", status);
1400 pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata,
1401 sip_err_code, NULL, NULL, NULL, NULL);
1402 goto on_return;
1403 }
1404*/
1405
1406 /* Init Session Timers */
1407 status = pjsip_timer_init_session(inv,
1408 &pjsua_var.acc[acc_id].cfg.timer_setting);
1409 if (status != PJ_SUCCESS) {
1410 pjsua_perror(THIS_FILE, "Session Timer init failed", status);
1411 pjsip_dlg_respond(dlg, rdata, PJSIP_SC_INTERNAL_SERVER_ERROR, NULL, NULL, NULL);
1412 pjsip_inv_terminate(inv, PJSIP_SC_INTERNAL_SERVER_ERROR, PJ_FALSE);
1413
1414 pjsua_media_channel_deinit(call->index);
1415 call->inv = NULL;
1416 call->async_call.dlg = NULL;
1417
1418 goto on_return;
1419 }
1420
1421 /* Update NAT type of remote endpoint, only when there is SDP in
1422 * incoming INVITE!
1423 */
1424 if (pjsua_var.ua_cfg.nat_type_in_sdp && inv->neg &&
1425 pjmedia_sdp_neg_get_state(inv->neg) > PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER)
1426 {
1427 const pjmedia_sdp_session *remote_sdp;
1428
1429 if (pjmedia_sdp_neg_get_neg_remote(inv->neg, &remote_sdp)==PJ_SUCCESS)
1430 update_remote_nat_type(call, remote_sdp);
1431 }
1432
1433 /* Must answer with some response to initial INVITE. We'll do this before
1434 * attaching the call to the invite session/dialog, so that the application
1435 * will not get notification about this event (on another scenario, it is
1436 * also possible that inv_send_msg() fails and causes the invite session to
1437 * be disconnected. If we have the call attached at this time, this will
1438 * cause the disconnection callback to be called before on_incoming_call()
1439 * callback is called, which is not right).
1440 */
1441 status = pjsip_inv_initial_answer(inv, rdata,
1442 100, NULL, NULL, &response);
1443 if (status != PJ_SUCCESS) {
1444 if (response == NULL) {
1445 pjsua_perror(THIS_FILE, "Unable to send answer to incoming INVITE",
1446 status);
1447 pjsip_dlg_respond(dlg, rdata, 500, NULL, NULL, NULL);
1448 pjsip_inv_terminate(inv, 500, PJ_FALSE);
1449 } else {
1450 pjsip_inv_send_msg(inv, response);
1451 pjsip_inv_terminate(inv, response->msg->line.status.code,
1452 PJ_FALSE);
1453 }
1454 pjsua_media_channel_deinit(call->index);
1455 call->inv = NULL;
1456 call->async_call.dlg = NULL;
1457 goto on_return;
1458
1459 } else {
1460 status = pjsip_inv_send_msg(inv, response);
1461 if (status != PJ_SUCCESS) {
1462 pjsua_perror(THIS_FILE, "Unable to send 100 response", status);
1463 pjsua_media_channel_deinit(call->index);
1464 call->inv = NULL;
1465 call->async_call.dlg = NULL;
1466 goto on_return;
1467 }
1468 }
1469
1470 /* Only do this after sending 100/Trying (really! see the long comment
1471 * above)
1472 */
1473 dlg->mod_data[pjsua_var.mod.id] = call;
1474 inv->mod_data[pjsua_var.mod.id] = call;
1475
1476 ++pjsua_var.call_cnt;
1477
1478 /* Check if this request should replace existing call */
1479 if (replaced_dlg) {
1480 /* Process call replace. If the media channel init has been completed,
1481 * just process now, otherwise, just queue the replaced dialog so
1482 * it will be processed once the media channel async init is finished
1483 * successfully.
1484 */
1485 if (call->med_ch_cb == NULL) {
1486 process_incoming_call_replace(call, replaced_dlg);
1487 } else {
1488 call->async_call.call_var.inc_call.replaced_dlg = replaced_dlg;
1489 }
1490 } else {
1491 /* Notify application if on_incoming_call() is overriden,
1492 * otherwise hangup the call with 480
1493 */
1494 if (pjsua_var.ua_cfg.cb.on_incoming_call) {
1495 pjsua_var.ua_cfg.cb.on_incoming_call(acc_id, call_id, rdata);
1496 } else {
1497 pjsua_call_hangup(call_id, PJSIP_SC_TEMPORARILY_UNAVAILABLE,
1498 NULL, NULL);
1499 }
1500 }
1501
1502
1503 /* This INVITE request has been handled. */
1504on_return:
1505 pj_log_pop_indent();
1506 PJSUA_UNLOCK();
1507 return PJ_TRUE;
1508}
1509
1510
1511
1512/*
1513 * Check if the specified call has active INVITE session and the INVITE
1514 * session has not been disconnected.
1515 */
1516PJ_DEF(pj_bool_t) pjsua_call_is_active(pjsua_call_id call_id)
1517{
1518 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
1519 PJ_EINVAL);
1520 return pjsua_var.calls[call_id].inv != NULL &&
1521 pjsua_var.calls[call_id].inv->state != PJSIP_INV_STATE_DISCONNECTED;
1522}
1523
1524
1525/* Acquire lock to the specified call_id */
1526pj_status_t acquire_call(const char *title,
1527 pjsua_call_id call_id,
1528 pjsua_call **p_call,
1529 pjsip_dialog **p_dlg)
1530{
1531 unsigned retry;
1532 pjsua_call *call = NULL;
1533 pj_bool_t has_pjsua_lock = PJ_FALSE;
1534 pj_status_t status = PJ_SUCCESS;
1535 pj_time_val time_start, timeout;
1536 pjsip_dialog *dlg = NULL;
1537
1538 pj_gettimeofday(&time_start);
1539 timeout.sec = 0;
1540 timeout.msec = PJSUA_ACQUIRE_CALL_TIMEOUT;
1541 pj_time_val_normalize(&timeout);
1542
1543 for (retry=0; ; ++retry) {
1544
1545 if (retry % 10 == 9) {
1546 pj_time_val dtime;
1547
1548 pj_gettimeofday(&dtime);
1549 PJ_TIME_VAL_SUB(dtime, time_start);
1550 if (!PJ_TIME_VAL_LT(dtime, timeout))
1551 break;
1552 }
1553
1554 has_pjsua_lock = PJ_FALSE;
1555
1556 status = PJSUA_TRY_LOCK();
1557 if (status != PJ_SUCCESS) {
1558 pj_thread_sleep(retry/10);
1559 continue;
1560 }
1561
1562 has_pjsua_lock = PJ_TRUE;
1563 call = &pjsua_var.calls[call_id];
1564 if (call->inv)
1565 dlg = call->inv->dlg;
1566 else
1567 dlg = call->async_call.dlg;
1568
1569 if (dlg == NULL) {
1570 PJSUA_UNLOCK();
1571 PJ_LOG(3,(THIS_FILE, "Invalid call_id %d in %s", call_id, title));
1572 return PJSIP_ESESSIONTERMINATED;
1573 }
1574
1575 status = pjsip_dlg_try_inc_lock(dlg);
1576 if (status != PJ_SUCCESS) {
1577 PJSUA_UNLOCK();
1578 pj_thread_sleep(retry/10);
1579 continue;
1580 }
1581
1582 PJSUA_UNLOCK();
1583
1584 break;
1585 }
1586
1587 if (status != PJ_SUCCESS) {
1588 if (has_pjsua_lock == PJ_FALSE)
1589 PJ_LOG(1,(THIS_FILE, "Timed-out trying to acquire PJSUA mutex "
1590 "(possibly system has deadlocked) in %s",
1591 title));
1592 else
1593 PJ_LOG(1,(THIS_FILE, "Timed-out trying to acquire dialog mutex "
1594 "(possibly system has deadlocked) in %s",
1595 title));
1596 return PJ_ETIMEDOUT;
1597 }
1598
1599 *p_call = call;
1600 *p_dlg = dlg;
1601
1602 return PJ_SUCCESS;
1603}
1604
1605
1606/*
1607 * Obtain detail information about the specified call.
1608 */
1609PJ_DEF(pj_status_t) pjsua_call_get_info( pjsua_call_id call_id,
1610 pjsua_call_info *info)
1611{
1612 pjsua_call *call;
1613 pjsip_dialog *dlg;
1614 unsigned mi;
1615
1616 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
1617 PJ_EINVAL);
1618
1619 pj_bzero(info, sizeof(*info));
1620
1621 /* Use PJSUA_LOCK() instead of acquire_call():
1622 * https://trac.pjsip.org/repos/ticket/1371
1623 */
1624 PJSUA_LOCK();
1625
1626 call = &pjsua_var.calls[call_id];
1627 dlg = (call->inv ? call->inv->dlg : call->async_call.dlg);
1628 if (!dlg) {
1629 PJSUA_UNLOCK();
1630 return PJSIP_ESESSIONTERMINATED;
1631 }
1632
1633 /* id and role */
1634 info->id = call_id;
1635 info->role = dlg->role;
1636 info->acc_id = call->acc_id;
1637
1638 /* local info */
1639 info->local_info.ptr = info->buf_.local_info;
1640 pj_strncpy(&info->local_info, &dlg->local.info_str,
1641 sizeof(info->buf_.local_info));
1642
1643 /* local contact */
1644 info->local_contact.ptr = info->buf_.local_contact;
1645 info->local_contact.slen = pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR,
1646 dlg->local.contact->uri,
1647 info->local_contact.ptr,
1648 sizeof(info->buf_.local_contact));
1649
1650 /* remote info */
1651 info->remote_info.ptr = info->buf_.remote_info;
1652 pj_strncpy(&info->remote_info, &dlg->remote.info_str,
1653 sizeof(info->buf_.remote_info));
1654
1655 /* remote contact */
1656 if (dlg->remote.contact) {
1657 int len;
1658 info->remote_contact.ptr = info->buf_.remote_contact;
1659 len = pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR,
1660 dlg->remote.contact->uri,
1661 info->remote_contact.ptr,
1662 sizeof(info->buf_.remote_contact));
1663 if (len < 0) len = 0;
1664 info->remote_contact.slen = len;
1665 } else {
1666 info->remote_contact.slen = 0;
1667 }
1668
1669 /* call id */
1670 info->call_id.ptr = info->buf_.call_id;
1671 pj_strncpy(&info->call_id, &dlg->call_id->id,
1672 sizeof(info->buf_.call_id));
1673
1674 /* call setting */
1675 pj_memcpy(&info->setting, &call->opt, sizeof(call->opt));
1676
1677 /* state, state_text */
1678 if (call->inv) {
1679 info->state = call->inv->state;
1680 } else if (call->async_call.dlg && call->last_code==0) {
1681 info->state = PJSIP_INV_STATE_NULL;
1682 } else {
1683 info->state = PJSIP_INV_STATE_DISCONNECTED;
1684 }
1685 info->state_text = pj_str((char*)pjsip_inv_state_name(info->state));
1686
1687 /* If call is disconnected, set the last_status from the cause code */
1688 if (call->inv && call->inv->state >= PJSIP_INV_STATE_DISCONNECTED) {
1689 /* last_status, last_status_text */
1690 info->last_status = call->inv->cause;
1691
1692 info->last_status_text.ptr = info->buf_.last_status_text;
1693 pj_strncpy(&info->last_status_text, &call->inv->cause_text,
1694 sizeof(info->buf_.last_status_text));
1695 } else {
1696 /* last_status, last_status_text */
1697 info->last_status = call->last_code;
1698
1699 info->last_status_text.ptr = info->buf_.last_status_text;
1700 pj_strncpy(&info->last_status_text, &call->last_text,
1701 sizeof(info->buf_.last_status_text));
1702 }
1703
1704 /* Audio & video count offered by remote */
1705 info->rem_offerer = call->rem_offerer;
1706 if (call->rem_offerer) {
1707 info->rem_aud_cnt = call->rem_aud_cnt;
1708 info->rem_vid_cnt = call->rem_vid_cnt;
1709 }
1710
1711 /* Build array of active media info */
1712 info->media_cnt = 0;
1713 for (mi=0; mi < call->med_cnt &&
1714 info->media_cnt < PJ_ARRAY_SIZE(info->media); ++mi)
1715 {
1716 pjsua_call_media *call_med = &call->media[mi];
1717
1718 info->media[info->media_cnt].index = mi;
1719 info->media[info->media_cnt].status = call_med->state;
1720 info->media[info->media_cnt].dir = call_med->dir;
1721 info->media[info->media_cnt].type = call_med->type;
1722
1723 if (call_med->type == PJMEDIA_TYPE_AUDIO) {
1724 info->media[info->media_cnt].stream.aud.conf_slot =
1725 call_med->strm.a.conf_slot;
1726 } else if (call_med->type == PJMEDIA_TYPE_VIDEO) {
1727 pjmedia_vid_dev_index cap_dev = PJMEDIA_VID_INVALID_DEV;
1728
1729 info->media[info->media_cnt].stream.vid.win_in =
1730 call_med->strm.v.rdr_win_id;
1731
1732 if (call_med->strm.v.cap_win_id != PJSUA_INVALID_ID) {
1733 cap_dev = call_med->strm.v.cap_dev;
1734 }
1735 info->media[info->media_cnt].stream.vid.cap_dev = cap_dev;
1736 } else {
1737 continue;
1738 }
1739 ++info->media_cnt;
1740 }
1741
1742 if (call->audio_idx != -1) {
1743 info->media_status = call->media[call->audio_idx].state;
1744 info->media_dir = call->media[call->audio_idx].dir;
1745 info->conf_slot = call->media[call->audio_idx].strm.a.conf_slot;
1746 }
1747
1748 /* Build array of provisional media info */
1749 info->prov_media_cnt = 0;
1750 for (mi=0; mi < call->med_prov_cnt &&
1751 info->prov_media_cnt < PJ_ARRAY_SIZE(info->prov_media); ++mi)
1752 {
1753 pjsua_call_media *call_med = &call->media_prov[mi];
1754
1755 info->prov_media[info->prov_media_cnt].index = mi;
1756 info->prov_media[info->prov_media_cnt].status = call_med->state;
1757 info->prov_media[info->prov_media_cnt].dir = call_med->dir;
1758 info->prov_media[info->prov_media_cnt].type = call_med->type;
1759 if (call_med->type == PJMEDIA_TYPE_AUDIO) {
1760 info->prov_media[info->prov_media_cnt].stream.aud.conf_slot =
1761 call_med->strm.a.conf_slot;
1762 } else if (call_med->type == PJMEDIA_TYPE_VIDEO) {
1763 pjmedia_vid_dev_index cap_dev = PJMEDIA_VID_INVALID_DEV;
1764
1765 info->prov_media[info->prov_media_cnt].stream.vid.win_in =
1766 call_med->strm.v.rdr_win_id;
1767
1768 if (call_med->strm.v.cap_win_id != PJSUA_INVALID_ID) {
1769 cap_dev = call_med->strm.v.cap_dev;
1770 }
1771 info->prov_media[info->prov_media_cnt].stream.vid.cap_dev=cap_dev;
1772 } else {
1773 continue;
1774 }
1775 ++info->prov_media_cnt;
1776 }
1777
1778 /* calculate duration */
1779 if (info->state >= PJSIP_INV_STATE_DISCONNECTED) {
1780
1781 info->total_duration = call->dis_time;
1782 PJ_TIME_VAL_SUB(info->total_duration, call->start_time);
1783
1784 if (call->conn_time.sec) {
1785 info->connect_duration = call->dis_time;
1786 PJ_TIME_VAL_SUB(info->connect_duration, call->conn_time);
1787 }
1788
1789 } else if (info->state == PJSIP_INV_STATE_CONFIRMED) {
1790
1791 pj_gettimeofday(&info->total_duration);
1792 PJ_TIME_VAL_SUB(info->total_duration, call->start_time);
1793
1794 pj_gettimeofday(&info->connect_duration);
1795 PJ_TIME_VAL_SUB(info->connect_duration, call->conn_time);
1796
1797 } else {
1798 pj_gettimeofday(&info->total_duration);
1799 PJ_TIME_VAL_SUB(info->total_duration, call->start_time);
1800 }
1801
1802 PJSUA_UNLOCK();
1803
1804 return PJ_SUCCESS;
1805}
1806
1807/*
1808 * Check if call remote peer support the specified capability.
1809 */
1810PJ_DEF(pjsip_dialog_cap_status) pjsua_call_remote_has_cap(
1811 pjsua_call_id call_id,
1812 int htype,
1813 const pj_str_t *hname,
1814 const pj_str_t *token)
1815{
1816 pjsua_call *call;
1817 pjsip_dialog *dlg;
1818 pj_status_t status;
1819 pjsip_dialog_cap_status cap_status;
1820
1821 status = acquire_call("pjsua_call_peer_has_cap()", call_id, &call, &dlg);
1822 if (status != PJ_SUCCESS)
1823 return PJSIP_DIALOG_CAP_UNKNOWN;
1824
1825 cap_status = pjsip_dlg_remote_has_cap(dlg, htype, hname, token);
1826
1827 pjsip_dlg_dec_lock(dlg);
1828
1829 return cap_status;
1830}
1831
1832
1833/*
1834 * Attach application specific data to the call.
1835 */
1836PJ_DEF(pj_status_t) pjsua_call_set_user_data( pjsua_call_id call_id,
1837 void *user_data)
1838{
1839 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
1840 PJ_EINVAL);
1841 pjsua_var.calls[call_id].user_data = user_data;
1842
1843 return PJ_SUCCESS;
1844}
1845
1846
1847/*
1848 * Get user data attached to the call.
1849 */
1850PJ_DEF(void*) pjsua_call_get_user_data(pjsua_call_id call_id)
1851{
1852 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
1853 NULL);
1854 return pjsua_var.calls[call_id].user_data;
1855}
1856
1857
1858/*
1859 * Get remote's NAT type.
1860 */
1861PJ_DEF(pj_status_t) pjsua_call_get_rem_nat_type(pjsua_call_id call_id,
1862 pj_stun_nat_type *p_type)
1863{
1864 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
1865 PJ_EINVAL);
1866 PJ_ASSERT_RETURN(p_type != NULL, PJ_EINVAL);
1867
1868 *p_type = pjsua_var.calls[call_id].rem_nat_type;
1869 return PJ_SUCCESS;
1870}
1871
1872
1873/*
1874 * Get media transport info for the specified media index.
1875 */
1876PJ_DEF(pj_status_t)
1877pjsua_call_get_med_transport_info(pjsua_call_id call_id,
1878 unsigned med_idx,
1879 pjmedia_transport_info *t)
1880{
1881 pjsua_call *call;
1882 pjsua_call_media *call_med;
1883 pj_status_t status;
1884
1885 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
1886 PJ_EINVAL);
1887 PJ_ASSERT_RETURN(t, PJ_EINVAL);
1888
1889 PJSUA_LOCK();
1890
1891 call = &pjsua_var.calls[call_id];
1892
1893 if (med_idx >= call->med_cnt) {
1894 PJSUA_UNLOCK();
1895 return PJ_EINVAL;
1896 }
1897
1898 call_med = &call->media[med_idx];
1899
1900 pjmedia_transport_info_init(t);
1901 status = pjmedia_transport_get_info(call_med->tp, t);
1902
1903 PJSUA_UNLOCK();
1904 return status;
1905}
1906
1907
1908/* Media channel init callback for pjsua_call_answer(). */
1909static pj_status_t
1910on_answer_call_med_tp_complete(pjsua_call_id call_id,
1911 const pjsua_med_tp_state_info *info)
1912{
1913 pjsua_call *call = &pjsua_var.calls[call_id];
1914 pjmedia_sdp_session *sdp;
1915 int sip_err_code = (info? info->sip_err_code: 0);
1916 pj_status_t status = (info? info->status: PJ_SUCCESS);
1917
1918 PJSUA_LOCK();
1919
1920 if (status != PJ_SUCCESS) {
1921 pjsua_perror(THIS_FILE, "Error initializing media channel", status);
1922 goto on_return;
1923 }
1924
1925 /* pjsua_media_channel_deinit() has been called. */
1926 if (call->async_call.med_ch_deinit) {
1927 pjsua_media_channel_deinit(call->index);
1928 call->med_ch_cb = NULL;
1929 PJSUA_UNLOCK();
1930 return PJ_SUCCESS;
1931 }
1932
1933 status = pjsua_media_channel_create_sdp(call_id,
1934 call->async_call.dlg->pool,
1935 NULL, &sdp, &sip_err_code);
1936 if (status != PJ_SUCCESS) {
1937 pjsua_perror(THIS_FILE, "Error creating SDP answer", status);
1938 goto on_return;
1939 }
1940
1941 status = pjsip_inv_set_local_sdp(call->inv, sdp);
1942 if (status != PJ_SUCCESS) {
1943 pjsua_perror(THIS_FILE, "Error setting local SDP", status);
1944 sip_err_code = PJSIP_SC_NOT_ACCEPTABLE_HERE;
1945 goto on_return;
1946 }
1947
1948on_return:
1949 if (status != PJ_SUCCESS) {
1950 /* If the callback is called from pjsua_call_on_incoming(), the
1951 * invite's state is PJSIP_INV_STATE_NULL, so the invite session
1952 * will be terminated later, otherwise we end the session here.
1953 */
1954 if (call->inv->state > PJSIP_INV_STATE_NULL) {
1955 pjsip_tx_data *tdata;
1956 pj_status_t status_;
1957
1958 status_ = pjsip_inv_end_session(call->inv, sip_err_code, NULL,
1959 &tdata);
1960 if (status_ == PJ_SUCCESS && tdata)
1961 status_ = pjsip_inv_send_msg(call->inv, tdata);
1962 }
1963
1964 pjsua_media_channel_deinit(call->index);
1965 }
1966
1967 /* Set the callback to NULL to indicate that the async operation
1968 * has completed.
1969 */
1970 call->med_ch_cb = NULL;
1971
1972 /* Finish any pending process */
1973 if (status == PJ_SUCCESS) {
1974 /* Process pending call answers */
1975 process_pending_call_answer(call);
1976 }
1977
1978 PJSUA_UNLOCK();
1979 return status;
1980}
1981
1982
1983/*
1984 * Send response to incoming INVITE request.
1985 */
1986PJ_DEF(pj_status_t) pjsua_call_answer( pjsua_call_id call_id,
1987 unsigned code,
1988 const pj_str_t *reason,
1989 const pjsua_msg_data *msg_data)
1990{
1991 return pjsua_call_answer2(call_id, NULL, code, reason, msg_data);
1992}
1993
1994
1995/*
1996 * Send response to incoming INVITE request.
1997 */
1998PJ_DEF(pj_status_t) pjsua_call_answer2(pjsua_call_id call_id,
1999 const pjsua_call_setting *opt,
2000 unsigned code,
2001 const pj_str_t *reason,
2002 const pjsua_msg_data *msg_data)
2003{
2004 pjsua_call *call;
2005 pjsip_dialog *dlg = NULL;
2006 pjsip_tx_data *tdata;
2007 pj_status_t status;
2008
2009 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
2010 PJ_EINVAL);
2011
2012 PJ_LOG(4,(THIS_FILE, "Answering call %d: code=%d", call_id, code));
2013 pj_log_push_indent();
2014
2015 status = acquire_call("pjsua_call_answer()", call_id, &call, &dlg);
2016 if (status != PJ_SUCCESS)
2017 goto on_return;
2018
2019 /* Apply call setting, only if status code is 1xx or 2xx. */
2020 if (opt && code < 300) {
2021 /* Check if it has not been set previously or it is different to
2022 * the previous one.
2023 */
2024 if (!call->opt_inited) {
2025 call->opt_inited = PJ_TRUE;
2026 apply_call_setting(call, opt, NULL);
2027 } else if (pj_memcmp(opt, &call->opt, sizeof(*opt)) != 0) {
2028 /* Warn application about call setting inconsistency */
2029 PJ_LOG(2,(THIS_FILE, "The call setting changes is ignored."));
2030 }
2031 }
2032
2033 PJSUA_LOCK();
2034
2035 /* Ticket #1526: When the incoming call contains no SDP offer, the media
2036 * channel may have not been initialized at this stage. The media channel
2037 * will be initialized here (along with SDP local offer generation) when
2038 * the following conditions are met:
2039 * - no pending media channel init
2040 * - local SDP has not been generated
2041 * - call setting has just been set, or SDP offer needs to be sent, i.e:
2042 * answer code 183 or 2xx is issued
2043 */
2044 if (!call->med_ch_cb &&
2045 (call->opt_inited || (code==183 || code/100==2)) &&
2046 (!call->inv->neg ||
2047 pjmedia_sdp_neg_get_state(call->inv->neg) ==
2048 PJMEDIA_SDP_NEG_STATE_NULL))
2049 {
2050 /* Mark call setting as initialized as it is just about to be used
2051 * for initializing the media channel.
2052 */
2053 call->opt_inited = PJ_TRUE;
2054
2055 status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAC,
2056 call->secure_level,
2057 dlg->pool,
2058 NULL, NULL, PJ_TRUE,
2059 &on_answer_call_med_tp_complete);
2060 if (status == PJ_SUCCESS) {
2061 status = on_answer_call_med_tp_complete(call->index, NULL);
2062 if (status != PJ_SUCCESS) {
2063 PJSUA_UNLOCK();
2064 goto on_return;
2065 }
2066 } else if (status != PJ_EPENDING) {
2067 PJSUA_UNLOCK();
2068 pjsua_perror(THIS_FILE, "Error initializing media channel", status);
2069 goto on_return;
2070 }
2071 }
2072
2073 /* If media transport creation is not yet completed, we will answer
2074 * the call in the media transport creation callback instead.
2075 */
2076 if (call->med_ch_cb) {
2077 struct call_answer *answer;
2078
2079 PJ_LOG(4,(THIS_FILE, "Pending answering call %d upon completion "
2080 "of media transport", call_id));
2081
2082 answer = PJ_POOL_ZALLOC_T(call->inv->pool_prov, struct call_answer);
2083 answer->code = code;
2084 if (opt) {
2085 answer->opt = PJ_POOL_ZALLOC_T(call->inv->pool_prov,
2086 pjsua_call_setting);
2087 *answer->opt = *opt;
2088 }
2089 if (reason) {
2090 pj_strdup(call->inv->pool_prov, answer->reason, reason);
2091 }
2092 if (msg_data) {
2093 answer->msg_data = pjsua_msg_data_clone(call->inv->pool_prov,
2094 msg_data);
2095 }
2096 pj_list_push_back(&call->async_call.call_var.inc_call.answers,
2097 answer);
2098
2099 PJSUA_UNLOCK();
2100 if (dlg) pjsip_dlg_dec_lock(dlg);
2101 pj_log_pop_indent();
2102 return status;
2103 }
2104
2105 PJSUA_UNLOCK();
2106
2107 if (call->res_time.sec == 0)
2108 pj_gettimeofday(&call->res_time);
2109
2110 if (reason && reason->slen == 0)
2111 reason = NULL;
2112
2113 /* Create response message */
2114 status = pjsip_inv_answer(call->inv, code, reason, NULL, &tdata);
2115 if (status != PJ_SUCCESS) {
2116 pjsua_perror(THIS_FILE, "Error creating response",
2117 status);
2118 goto on_return;
2119 }
2120
2121 /* Call might have been disconnected if application is answering with
2122 * 200/OK and the media failed to start.
2123 */
2124 if (call->inv == NULL)
2125 goto on_return;
2126
2127 /* Add additional headers etc */
2128 pjsua_process_msg_data( tdata, msg_data);
2129
2130 /* Send the message */
2131 status = pjsip_inv_send_msg(call->inv, tdata);
2132 if (status != PJ_SUCCESS)
2133 pjsua_perror(THIS_FILE, "Error sending response",
2134 status);
2135
2136on_return:
2137 if (dlg) pjsip_dlg_dec_lock(dlg);
2138 pj_log_pop_indent();
2139 return status;
2140}
2141
2142
2143/*
2144 * Hangup call by using method that is appropriate according to the
2145 * call state.
2146 */
2147PJ_DEF(pj_status_t) pjsua_call_hangup(pjsua_call_id call_id,
2148 unsigned code,
2149 const pj_str_t *reason,
2150 const pjsua_msg_data *msg_data)
2151{
2152 pjsua_call *call;
2153 pjsip_dialog *dlg = NULL;
2154 pj_status_t status;
2155 pjsip_tx_data *tdata;
2156
2157
2158 if (call_id<0 || call_id>=(int)pjsua_var.ua_cfg.max_calls) {
2159 PJ_LOG(1,(THIS_FILE, "pjsua_call_hangup(): invalid call id %d",
2160 call_id));
2161 }
2162
2163 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
2164 PJ_EINVAL);
2165
2166 PJ_LOG(4,(THIS_FILE, "Call %d hanging up: code=%d..", call_id, code));
2167 pj_log_push_indent();
2168
2169 status = acquire_call("pjsua_call_hangup()", call_id, &call, &dlg);
2170 if (status != PJ_SUCCESS)
2171 goto on_return;
2172
2173 /* If media transport creation is not yet completed, we will hangup
2174 * the call in the media transport creation callback instead.
2175 */
2176 if (call->med_ch_cb && !call->inv) {
2177 PJ_LOG(4,(THIS_FILE, "Pending call %d hangup upon completion "
2178 "of media transport", call_id));
2179 call->async_call.call_var.out_call.hangup = PJ_TRUE;
2180 if (code == 0)
2181 call->last_code = PJSIP_SC_REQUEST_TERMINATED;
2182 else
2183 call->last_code = (pjsip_status_code)code;
2184 if (reason) {
2185 pj_strncpy(&call->last_text, reason,
2186 sizeof(call->last_text_buf_));
2187 }
2188
2189 goto on_return;
2190 }
2191
2192 if (code==0) {
2193 if (call->inv->state == PJSIP_INV_STATE_CONFIRMED)
2194 code = PJSIP_SC_OK;
2195 else if (call->inv->role == PJSIP_ROLE_UAS)
2196 code = PJSIP_SC_DECLINE;
2197 else
2198 code = PJSIP_SC_REQUEST_TERMINATED;
2199 }
2200
2201 status = pjsip_inv_end_session(call->inv, code, reason, &tdata);
2202 if (status != PJ_SUCCESS) {
2203 pjsua_perror(THIS_FILE,
2204 "Failed to create end session message",
2205 status);
2206 goto on_return;
2207 }
2208
2209 /* pjsip_inv_end_session may return PJ_SUCCESS with NULL
2210 * as p_tdata when INVITE transaction has not been answered
2211 * with any provisional responses.
2212 */
2213 if (tdata == NULL)
2214 goto on_return;
2215
2216 /* Add additional headers etc */
2217 pjsua_process_msg_data( tdata, msg_data);
2218
2219 /* Send the message */
2220 status = pjsip_inv_send_msg(call->inv, tdata);
2221 if (status != PJ_SUCCESS) {
2222 pjsua_perror(THIS_FILE,
2223 "Failed to send end session message",
2224 status);
2225 goto on_return;
2226 }
2227
2228 /* Stop reinvite timer, if it is active */
2229 if (call->reinv_timer.id) {
2230 pjsua_cancel_timer(&call->reinv_timer);
2231 call->reinv_timer.id = PJ_FALSE;
2232 }
2233
2234on_return:
2235 if (dlg) pjsip_dlg_dec_lock(dlg);
2236 pj_log_pop_indent();
2237 return status;
2238}
2239
2240
2241/*
2242 * Accept or reject redirection.
2243 */
2244PJ_DEF(pj_status_t) pjsua_call_process_redirect( pjsua_call_id call_id,
2245 pjsip_redirect_op cmd)
2246{
2247 pjsua_call *call;
2248 pjsip_dialog *dlg;
2249 pj_status_t status;
2250
2251 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
2252 PJ_EINVAL);
2253
2254 status = acquire_call("pjsua_call_process_redirect()", call_id,
2255 &call, &dlg);
2256 if (status != PJ_SUCCESS)
2257 return status;
2258
2259 status = pjsip_inv_process_redirect(call->inv, cmd, NULL);
2260
2261 pjsip_dlg_dec_lock(dlg);
2262
2263 return status;
2264}
2265
2266
2267/*
2268 * Put the specified call on hold.
2269 */
2270PJ_DEF(pj_status_t) pjsua_call_set_hold(pjsua_call_id call_id,
2271 const pjsua_msg_data *msg_data)
2272{
2273 return pjsua_call_set_hold2(call_id, 0, msg_data);
2274}
2275
2276PJ_DEF(pj_status_t) pjsua_call_set_hold2(pjsua_call_id call_id,
2277 unsigned options,
2278 const pjsua_msg_data *msg_data)
2279{
2280 pjmedia_sdp_session *sdp;
2281 pjsua_call *call;
2282 pjsip_dialog *dlg = NULL;
2283 pjsip_tx_data *tdata;
2284 pj_str_t *new_contact = NULL;
2285 pj_status_t status;
2286
2287 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
2288 PJ_EINVAL);
2289
2290 PJ_LOG(4,(THIS_FILE, "Putting call %d on hold", call_id));
2291 pj_log_push_indent();
2292
2293 status = acquire_call("pjsua_call_set_hold()", call_id, &call, &dlg);
2294 if (status != PJ_SUCCESS)
2295 goto on_return;
2296
2297 if (call->inv->state != PJSIP_INV_STATE_CONFIRMED) {
2298 PJ_LOG(3,(THIS_FILE, "Can not hold call that is not confirmed"));
2299 status = PJSIP_ESESSIONSTATE;
2300 goto on_return;
2301 }
2302
2303 status = create_sdp_of_call_hold(call, &sdp);
2304 if (status != PJ_SUCCESS)
2305 goto on_return;
2306
2307 if ((options & PJSUA_CALL_UPDATE_CONTACT) &&
2308 pjsua_acc_is_valid(call->acc_id))
2309 {
2310 new_contact = &pjsua_var.acc[call->acc_id].contact;
2311 }
2312
2313 /* Create re-INVITE with new offer */
2314 status = pjsip_inv_reinvite( call->inv, new_contact, sdp, &tdata);
2315 if (status != PJ_SUCCESS) {
2316 pjsua_perror(THIS_FILE, "Unable to create re-INVITE", status);
2317 goto on_return;
2318 }
2319
2320 /* Add additional headers etc */
2321 pjsua_process_msg_data( tdata, msg_data);
2322
2323 /* Record the tx_data to keep track the operation */
2324 call->hold_msg = (void*) tdata;
2325
2326 /* Send the request */
2327 status = pjsip_inv_send_msg( call->inv, tdata);
2328 if (status != PJ_SUCCESS) {
2329 pjsua_perror(THIS_FILE, "Unable to send re-INVITE", status);
2330 call->hold_msg = NULL;
2331 goto on_return;
2332 }
2333
2334 /* Set flag that local put the call on hold */
2335 call->local_hold = PJ_TRUE;
2336
2337on_return:
2338 if (dlg) pjsip_dlg_dec_lock(dlg);
2339 pj_log_pop_indent();
2340 return status;
2341}
2342
2343
2344/*
2345 * Send re-INVITE (to release hold).
2346 */
2347PJ_DEF(pj_status_t) pjsua_call_reinvite( pjsua_call_id call_id,
2348 unsigned options,
2349 const pjsua_msg_data *msg_data)
2350{
2351 pjsua_call *call;
2352 pjsip_dialog *dlg = NULL;
2353 pj_status_t status;
2354
2355 status = acquire_call("pjsua_call_reinvite()", call_id, &call, &dlg);
2356 if (status != PJ_SUCCESS)
2357 goto on_return;
2358
2359 if (options != call->opt.flag)
2360 call->opt.flag = options;
2361
2362 status = pjsua_call_reinvite2(call_id, NULL, msg_data);
2363
2364on_return:
2365 if (dlg) pjsip_dlg_dec_lock(dlg);
2366 return status;
2367}
2368
2369
2370/*
2371 * Send re-INVITE (to release hold).
2372 */
2373PJ_DEF(pj_status_t) pjsua_call_reinvite2(pjsua_call_id call_id,
2374 const pjsua_call_setting *opt,
2375 const pjsua_msg_data *msg_data)
2376{
2377 pjmedia_sdp_session *sdp;
2378 pj_str_t *new_contact = NULL;
2379 pjsip_tx_data *tdata;
2380 pjsua_call *call;
2381 pjsip_dialog *dlg = NULL;
2382 pj_status_t status;
2383
2384
2385 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
2386 PJ_EINVAL);
2387
2388 PJ_LOG(4,(THIS_FILE, "Sending re-INVITE on call %d", call_id));
2389 pj_log_push_indent();
2390
2391 status = acquire_call("pjsua_call_reinvite2()", call_id, &call, &dlg);
2392 if (status != PJ_SUCCESS)
2393 goto on_return;
2394
2395 if (call->inv->state != PJSIP_INV_STATE_CONFIRMED) {
2396 PJ_LOG(3,(THIS_FILE, "Can not re-INVITE call that is not confirmed"));
2397 status = PJSIP_ESESSIONSTATE;
2398 goto on_return;
2399 }
2400
2401 status = apply_call_setting(call, opt, NULL);
2402 if (status != PJ_SUCCESS) {
2403 pjsua_perror(THIS_FILE, "Failed to apply call setting", status);
2404 goto on_return;
2405 }
2406
2407 /* Create SDP */
2408 if (call->local_hold && (call->opt.flag & PJSUA_CALL_UNHOLD)==0) {
2409 status = create_sdp_of_call_hold(call, &sdp);
2410 } else {
2411 status = pjsua_media_channel_create_sdp(call->index,
2412 call->inv->pool_prov,
2413 NULL, &sdp, NULL);
2414 call->local_hold = PJ_FALSE;
2415 }
2416 if (status != PJ_SUCCESS) {
2417 pjsua_perror(THIS_FILE, "Unable to get SDP from media endpoint",
2418 status);
2419 goto on_return;
2420 }
2421
2422 if ((call->opt.flag & PJSUA_CALL_UPDATE_CONTACT) &&
2423 pjsua_acc_is_valid(call->acc_id))
2424 {
2425 new_contact = &pjsua_var.acc[call->acc_id].contact;
2426 }
2427
2428 /* Create re-INVITE with new offer */
2429 status = pjsip_inv_reinvite( call->inv, new_contact, sdp, &tdata);
2430 if (status != PJ_SUCCESS) {
2431 pjsua_perror(THIS_FILE, "Unable to create re-INVITE", status);
2432 goto on_return;
2433 }
2434
2435 /* Add additional headers etc */
2436 pjsua_process_msg_data( tdata, msg_data);
2437
2438 /* Send the request */
2439 status = pjsip_inv_send_msg( call->inv, tdata);
2440 if (status != PJ_SUCCESS) {
2441 pjsua_perror(THIS_FILE, "Unable to send re-INVITE", status);
2442 goto on_return;
2443 }
2444
2445on_return:
2446 if (dlg) pjsip_dlg_dec_lock(dlg);
2447 pj_log_pop_indent();
2448 return status;
2449}
2450
2451
2452/*
2453 * Send UPDATE request.
2454 */
2455PJ_DEF(pj_status_t) pjsua_call_update( pjsua_call_id call_id,
2456 unsigned options,
2457 const pjsua_msg_data *msg_data)
2458{
2459 pjsua_call *call;
2460 pjsip_dialog *dlg = NULL;
2461 pj_status_t status;
2462
2463 status = acquire_call("pjsua_call_update()", call_id, &call, &dlg);
2464 if (status != PJ_SUCCESS)
2465 goto on_return;
2466
2467 if (options != call->opt.flag)
2468 call->opt.flag = options;
2469
2470 status = pjsua_call_update2(call_id, NULL, msg_data);
2471
2472on_return:
2473 if (dlg) pjsip_dlg_dec_lock(dlg);
2474 return status;
2475}
2476
2477
2478/*
2479 * Send UPDATE request.
2480 */
2481PJ_DEF(pj_status_t) pjsua_call_update2(pjsua_call_id call_id,
2482 const pjsua_call_setting *opt,
2483 const pjsua_msg_data *msg_data)
2484{
2485 pjmedia_sdp_session *sdp;
2486 pj_str_t *new_contact = NULL;
2487 pjsip_tx_data *tdata;
2488 pjsua_call *call;
2489 pjsip_dialog *dlg = NULL;
2490 pj_status_t status;
2491
2492 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
2493 PJ_EINVAL);
2494
2495 PJ_LOG(4,(THIS_FILE, "Sending UPDATE on call %d", call_id));
2496 pj_log_push_indent();
2497
2498 status = acquire_call("pjsua_call_update2()", call_id, &call, &dlg);
2499 if (status != PJ_SUCCESS)
2500 goto on_return;
2501
2502 status = apply_call_setting(call, opt, NULL);
2503 if (status != PJ_SUCCESS) {
2504 pjsua_perror(THIS_FILE, "Failed to apply call setting", status);
2505 goto on_return;
2506 }
2507
2508 /* Create SDP */
2509 if (call->local_hold && (call->opt.flag & PJSUA_CALL_UNHOLD)==0) {
2510 status = create_sdp_of_call_hold(call, &sdp);
2511 } else {
2512 status = pjsua_media_channel_create_sdp(call->index,
2513 call->inv->pool_prov,
2514 NULL, &sdp, NULL);
2515 call->local_hold = PJ_FALSE;
2516 }
2517
2518 if (status != PJ_SUCCESS) {
2519 pjsua_perror(THIS_FILE, "Unable to get SDP from media endpoint",
2520 status);
2521 goto on_return;
2522 }
2523
2524 if ((call->opt.flag & PJSUA_CALL_UPDATE_CONTACT) &&
2525 pjsua_acc_is_valid(call->acc_id))
2526 {
2527 new_contact = &pjsua_var.acc[call->acc_id].contact;
2528 }
2529
2530 /* Create UPDATE with new offer */
2531 status = pjsip_inv_update(call->inv, new_contact, sdp, &tdata);
2532 if (status != PJ_SUCCESS) {
2533 pjsua_perror(THIS_FILE, "Unable to create UPDATE request", status);
2534 goto on_return;
2535 }
2536
2537 /* Add additional headers etc */
2538 pjsua_process_msg_data( tdata, msg_data);
2539
2540 /* Send the request */
2541 status = pjsip_inv_send_msg( call->inv, tdata);
2542 if (status != PJ_SUCCESS) {
2543 pjsua_perror(THIS_FILE, "Unable to send UPDATE request", status);
2544 goto on_return;
2545 }
2546
2547on_return:
2548 if (dlg) pjsip_dlg_dec_lock(dlg);
2549 pj_log_pop_indent();
2550 return status;
2551}
2552
2553
2554/*
2555 * Initiate call transfer to the specified address.
2556 */
2557PJ_DEF(pj_status_t) pjsua_call_xfer( pjsua_call_id call_id,
2558 const pj_str_t *dest,
2559 const pjsua_msg_data *msg_data)
2560{
2561 pjsip_evsub *sub;
2562 pjsip_tx_data *tdata;
2563 pjsua_call *call;
2564 pjsip_dialog *dlg = NULL;
2565 pjsip_generic_string_hdr *gs_hdr;
2566 const pj_str_t str_ref_by = { "Referred-By", 11 };
2567 struct pjsip_evsub_user xfer_cb;
2568 pj_status_t status;
2569
2570
2571 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls &&
2572 dest, PJ_EINVAL);
2573
2574 PJ_LOG(4,(THIS_FILE, "Transfering call %d to %.*s", call_id,
2575 (int)dest->slen, dest->ptr));
2576 pj_log_push_indent();
2577
2578 status = acquire_call("pjsua_call_xfer()", call_id, &call, &dlg);
2579 if (status != PJ_SUCCESS)
2580 goto on_return;
2581
2582 /* Create xfer client subscription. */
2583 pj_bzero(&xfer_cb, sizeof(xfer_cb));
2584 xfer_cb.on_evsub_state = &xfer_client_on_evsub_state;
2585
2586 status = pjsip_xfer_create_uac(call->inv->dlg, &xfer_cb, &sub);
2587 if (status != PJ_SUCCESS) {
2588 pjsua_perror(THIS_FILE, "Unable to create xfer", status);
2589 goto on_return;
2590 }
2591
2592 /* Associate this call with the client subscription */
2593 pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, call);
2594
2595 /*
2596 * Create REFER request.
2597 */
2598 status = pjsip_xfer_initiate(sub, dest, &tdata);
2599 if (status != PJ_SUCCESS) {
2600 pjsua_perror(THIS_FILE, "Unable to create REFER request", status);
2601 goto on_return;
2602 }
2603
2604 /* Add Referred-By header */
2605 gs_hdr = pjsip_generic_string_hdr_create(tdata->pool, &str_ref_by,
2606 &dlg->local.info_str);
2607 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)gs_hdr);
2608
2609
2610 /* Add additional headers etc */
2611 pjsua_process_msg_data( tdata, msg_data);
2612
2613 /* Send. */
2614 status = pjsip_xfer_send_request(sub, tdata);
2615 if (status != PJ_SUCCESS) {
2616 pjsua_perror(THIS_FILE, "Unable to send REFER request", status);
2617 goto on_return;
2618 }
2619
2620 /* For simplicity (that's what this program is intended to be!),
2621 * leave the original invite session as it is. More advanced application
2622 * may want to hold the INVITE, or terminate the invite, or whatever.
2623 */
2624on_return:
2625 if (dlg) pjsip_dlg_dec_lock(dlg);
2626 pj_log_pop_indent();
2627 return status;
2628
2629}
2630
2631
2632/*
2633 * Initiate attended call transfer to the specified address.
2634 */
2635PJ_DEF(pj_status_t) pjsua_call_xfer_replaces( pjsua_call_id call_id,
2636 pjsua_call_id dest_call_id,
2637 unsigned options,
2638 const pjsua_msg_data *msg_data)
2639{
2640 pjsua_call *dest_call;
2641 pjsip_dialog *dest_dlg;
2642 char str_dest_buf[PJSIP_MAX_URL_SIZE*2];
2643 pj_str_t str_dest;
2644 int len;
2645 pjsip_uri *uri;
2646 pj_status_t status;
2647
2648
2649 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
2650 PJ_EINVAL);
2651 PJ_ASSERT_RETURN(dest_call_id>=0 &&
2652 dest_call_id<(int)pjsua_var.ua_cfg.max_calls,
2653 PJ_EINVAL);
2654
2655 PJ_LOG(4,(THIS_FILE, "Transfering call %d replacing with call %d",
2656 call_id, dest_call_id));
2657 pj_log_push_indent();
2658
2659 status = acquire_call("pjsua_call_xfer_replaces()", dest_call_id,
2660 &dest_call, &dest_dlg);
2661 if (status != PJ_SUCCESS) {
2662 pj_log_pop_indent();
2663 return status;
2664 }
2665
2666 /*
2667 * Create REFER destination URI with Replaces field.
2668 */
2669
2670 /* Make sure we have sufficient buffer's length */
2671 PJ_ASSERT_ON_FAIL(dest_dlg->remote.info_str.slen +
2672 dest_dlg->call_id->id.slen +
2673 dest_dlg->remote.info->tag.slen +
2674 dest_dlg->local.info->tag.slen + 32
2675 < (long)sizeof(str_dest_buf),
2676 { status=PJSIP_EURITOOLONG; goto on_error; });
2677
2678 /* Print URI */
2679 str_dest_buf[0] = '<';
2680 str_dest.slen = 1;
2681
2682 uri = (pjsip_uri*) pjsip_uri_get_uri(dest_dlg->remote.info->uri);
2683 len = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, uri,
2684 str_dest_buf+1, sizeof(str_dest_buf)-1);
2685 if (len < 0) {
2686 status = PJSIP_EURITOOLONG;
2687 goto on_error;
2688 }
2689
2690 str_dest.slen += len;
2691
2692
2693 /* Build the URI */
2694 len = pj_ansi_snprintf(str_dest_buf + str_dest.slen,
2695 sizeof(str_dest_buf) - str_dest.slen,
2696 "?%s"
2697 "Replaces=%.*s"
2698 "%%3Bto-tag%%3D%.*s"
2699 "%%3Bfrom-tag%%3D%.*s>",
2700 ((options&PJSUA_XFER_NO_REQUIRE_REPLACES) ?
2701 "" : "Require=replaces&"),
2702 (int)dest_dlg->call_id->id.slen,
2703 dest_dlg->call_id->id.ptr,
2704 (int)dest_dlg->remote.info->tag.slen,
2705 dest_dlg->remote.info->tag.ptr,
2706 (int)dest_dlg->local.info->tag.slen,
2707 dest_dlg->local.info->tag.ptr);
2708
2709 PJ_ASSERT_ON_FAIL(len > 0 && len <= (int)sizeof(str_dest_buf)-str_dest.slen,
2710 { status=PJSIP_EURITOOLONG; goto on_error; });
2711
2712 str_dest.ptr = str_dest_buf;
2713 str_dest.slen += len;
2714
2715 pjsip_dlg_dec_lock(dest_dlg);
2716
2717 status = pjsua_call_xfer(call_id, &str_dest, msg_data);
2718
2719 pj_log_pop_indent();
2720 return status;
2721
2722on_error:
2723 if (dest_dlg) pjsip_dlg_dec_lock(dest_dlg);
2724 pj_log_pop_indent();
2725 return status;
2726}
2727
2728
2729/**
2730 * Send instant messaging inside INVITE session.
2731 */
2732PJ_DEF(pj_status_t) pjsua_call_send_im( pjsua_call_id call_id,
2733 const pj_str_t *mime_type,
2734 const pj_str_t *content,
2735 const pjsua_msg_data *msg_data,
2736 void *user_data)
2737{
2738 pjsua_call *call;
2739 pjsip_dialog *dlg = NULL;
2740 const pj_str_t mime_text_plain = pj_str("text/plain");
2741 pjsip_media_type ctype;
2742 pjsua_im_data *im_data;
2743 pjsip_tx_data *tdata;
2744 pj_status_t status;
2745
2746 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
2747 PJ_EINVAL);
2748
2749 PJ_LOG(4,(THIS_FILE, "Call %d sending %d bytes MESSAGE..",
2750 call_id, (int)content->slen));
2751 pj_log_push_indent();
2752
2753 status = acquire_call("pjsua_call_send_im()", call_id, &call, &dlg);
2754 if (status != PJ_SUCCESS)
2755 goto on_return;
2756
2757 /* Set default media type if none is specified */
2758 if (mime_type == NULL) {
2759 mime_type = &mime_text_plain;
2760 }
2761
2762 /* Create request message. */
2763 status = pjsip_dlg_create_request( call->inv->dlg, &pjsip_message_method,
2764 -1, &tdata);
2765 if (status != PJ_SUCCESS) {
2766 pjsua_perror(THIS_FILE, "Unable to create MESSAGE request", status);
2767 goto on_return;
2768 }
2769
2770 /* Add accept header. */
2771 pjsip_msg_add_hdr( tdata->msg,
2772 (pjsip_hdr*)pjsua_im_create_accept(tdata->pool));
2773
2774 /* Parse MIME type */
2775 pjsua_parse_media_type(tdata->pool, mime_type, &ctype);
2776
2777 /* Create "text/plain" message body. */
2778 tdata->msg->body = pjsip_msg_body_create( tdata->pool, &ctype.type,
2779 &ctype.subtype, content);
2780 if (tdata->msg->body == NULL) {
2781 pjsua_perror(THIS_FILE, "Unable to create msg body", PJ_ENOMEM);
2782 pjsip_tx_data_dec_ref(tdata);
2783 goto on_return;
2784 }
2785
2786 /* Add additional headers etc */
2787 pjsua_process_msg_data( tdata, msg_data);
2788
2789 /* Create IM data and attach to the request. */
2790 im_data = PJ_POOL_ZALLOC_T(tdata->pool, pjsua_im_data);
2791 im_data->acc_id = call->acc_id;
2792 im_data->call_id = call_id;
2793 im_data->to = call->inv->dlg->remote.info_str;
2794 pj_strdup_with_null(tdata->pool, &im_data->body, content);
2795 im_data->user_data = user_data;
2796
2797
2798 /* Send the request. */
2799 status = pjsip_dlg_send_request( call->inv->dlg, tdata,
2800 pjsua_var.mod.id, im_data);
2801 if (status != PJ_SUCCESS) {
2802 pjsua_perror(THIS_FILE, "Unable to send MESSAGE request", status);
2803 goto on_return;
2804 }
2805
2806on_return:
2807 if (dlg) pjsip_dlg_dec_lock(dlg);
2808 pj_log_pop_indent();
2809 return status;
2810}
2811
2812
2813/*
2814 * Send IM typing indication inside INVITE session.
2815 */
2816PJ_DEF(pj_status_t) pjsua_call_send_typing_ind( pjsua_call_id call_id,
2817 pj_bool_t is_typing,
2818 const pjsua_msg_data*msg_data)
2819{
2820 pjsua_call *call;
2821 pjsip_dialog *dlg = NULL;
2822 pjsip_tx_data *tdata;
2823 pj_status_t status;
2824
2825 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
2826 PJ_EINVAL);
2827
2828 PJ_LOG(4,(THIS_FILE, "Call %d sending typing indication..",
2829 call_id));
2830 pj_log_push_indent();
2831
2832 status = acquire_call("pjsua_call_send_typing_ind", call_id, &call, &dlg);
2833 if (status != PJ_SUCCESS)
2834 goto on_return;
2835
2836 /* Create request message. */
2837 status = pjsip_dlg_create_request( call->inv->dlg, &pjsip_message_method,
2838 -1, &tdata);
2839 if (status != PJ_SUCCESS) {
2840 pjsua_perror(THIS_FILE, "Unable to create MESSAGE request", status);
2841 goto on_return;
2842 }
2843
2844 /* Create "application/im-iscomposing+xml" msg body. */
2845 tdata->msg->body = pjsip_iscomposing_create_body(tdata->pool, is_typing,
2846 NULL, NULL, -1);
2847
2848 /* Add additional headers etc */
2849 pjsua_process_msg_data( tdata, msg_data);
2850
2851 /* Send the request. */
2852 status = pjsip_dlg_send_request( call->inv->dlg, tdata, -1, NULL);
2853 if (status != PJ_SUCCESS) {
2854 pjsua_perror(THIS_FILE, "Unable to send MESSAGE request", status);
2855 goto on_return;
2856 }
2857
2858on_return:
2859 if (dlg) pjsip_dlg_dec_lock(dlg);
2860 pj_log_pop_indent();
2861 return status;
2862}
2863
2864
2865/*
2866 * Send arbitrary request.
2867 */
2868PJ_DEF(pj_status_t) pjsua_call_send_request(pjsua_call_id call_id,
2869 const pj_str_t *method_str,
2870 const pjsua_msg_data *msg_data)
2871{
2872 pjsua_call *call;
2873 pjsip_dialog *dlg = NULL;
2874 pjsip_method method;
2875 pjsip_tx_data *tdata;
2876 pj_status_t status;
2877
2878 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
2879 PJ_EINVAL);
2880
2881 PJ_LOG(4,(THIS_FILE, "Call %d sending %.*s request..",
2882 call_id, (int)method_str->slen, method_str->ptr));
2883 pj_log_push_indent();
2884
2885 status = acquire_call("pjsua_call_send_request", call_id, &call, &dlg);
2886 if (status != PJ_SUCCESS)
2887 goto on_return;
2888
2889 /* Init method */
2890 pjsip_method_init_np(&method, (pj_str_t*)method_str);
2891
2892 /* Create request message. */
2893 status = pjsip_dlg_create_request( call->inv->dlg, &method, -1, &tdata);
2894 if (status != PJ_SUCCESS) {
2895 pjsua_perror(THIS_FILE, "Unable to create request", status);
2896 goto on_return;
2897 }
2898
2899 /* Add additional headers etc */
2900 pjsua_process_msg_data( tdata, msg_data);
2901
2902 /* Send the request. */
2903 status = pjsip_dlg_send_request( call->inv->dlg, tdata, -1, NULL);
2904 if (status != PJ_SUCCESS) {
2905 pjsua_perror(THIS_FILE, "Unable to send request", status);
2906 goto on_return;
2907 }
2908
2909on_return:
2910 if (dlg) pjsip_dlg_dec_lock(dlg);
2911 pj_log_pop_indent();
2912 return status;
2913}
2914
2915
2916/*
2917 * Terminate all calls.
2918 */
2919PJ_DEF(void) pjsua_call_hangup_all(void)
2920{
2921 unsigned i;
2922
2923 PJ_LOG(4,(THIS_FILE, "Hangup all calls.."));
2924 pj_log_push_indent();
2925
2926 // This may deadlock, see https://trac.pjsip.org/repos/ticket/1305
2927 //PJSUA_LOCK();
2928
2929 for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) {
2930 if (pjsua_var.calls[i].inv)
2931 pjsua_call_hangup(i, 0, NULL, NULL);
2932 }
2933
2934 //PJSUA_UNLOCK();
2935 pj_log_pop_indent();
2936}
2937
2938
2939/* Timer callback to send re-INVITE/UPDATE to lock codec or ICE update */
2940static void reinv_timer_cb(pj_timer_heap_t *th, pj_timer_entry *entry)
2941{
2942 pjsua_call_id call_id = (pjsua_call_id)(pj_size_t)entry->user_data;
2943 pjsip_dialog *dlg;
2944 pjsua_call *call;
2945 pj_status_t status;
2946
2947 PJ_UNUSED_ARG(th);
2948
2949 pjsua_var.calls[call_id].reinv_timer.id = PJ_FALSE;
2950
2951 pj_log_push_indent();
2952
2953 status = acquire_call("reinv_timer_cb()", call_id, &call, &dlg);
2954 if (status != PJ_SUCCESS) {
2955 pj_log_pop_indent();
2956 return;
2957 }
2958
2959 process_pending_reinvite(call);
2960
2961 pjsip_dlg_dec_lock(dlg);
2962
2963 pj_log_pop_indent();
2964}
2965
2966
2967/* Check if the specified format can be skipped in counting codecs */
2968static pj_bool_t is_non_av_fmt(const pjmedia_sdp_media *m,
2969 const pj_str_t *fmt)
2970{
2971 const pj_str_t STR_TEL = {"telephone-event", 15};
2972 unsigned pt;
2973
2974 pt = pj_strtoul(fmt);
2975
2976 /* Check for comfort noise */
2977 if (pt == PJMEDIA_RTP_PT_CN)
2978 return PJ_TRUE;
2979
2980 /* Dynamic PT, check the format name */
2981 if (pt >= 96) {
2982 pjmedia_sdp_attr *a;
2983 pjmedia_sdp_rtpmap rtpmap;
2984
2985 /* Get the format name */
2986 a = pjmedia_sdp_attr_find2(m->attr_count, m->attr, "rtpmap", fmt);
2987 if (a && pjmedia_sdp_attr_get_rtpmap(a, &rtpmap)==PJ_SUCCESS) {
2988 /* Check for telephone-event */
2989 if (pj_stricmp(&rtpmap.enc_name, &STR_TEL)==0)
2990 return PJ_TRUE;
2991 } else {
2992 /* Invalid SDP, should not reach here */
2993 pj_assert(!"SDP should have been validated!");
2994 return PJ_TRUE;
2995 }
2996 }
2997
2998 return PJ_FALSE;
2999}
3000
3001
3002/* Schedule check for the need of re-INVITE/UPDATE after media update, cases:
3003 * - lock codec if remote answerer has given us more than one codecs
3004 * - update ICE default transport address if it has changed after ICE
3005 * connectivity check.
3006 */
3007void pjsua_call_schedule_reinvite_check(pjsua_call *call, unsigned delay_ms)
3008{
3009 pj_time_val delay;
3010
3011 /* Stop reinvite timer, if it is active */
3012 if (call->reinv_timer.id)
3013 pjsua_cancel_timer(&call->reinv_timer);
3014
3015 delay.sec = 0;
3016 delay.msec = delay_ms;
3017 pj_time_val_normalize(&delay);
3018 call->reinv_timer.id = PJ_TRUE;
3019 pjsua_schedule_timer(&call->reinv_timer, &delay);
3020}
3021
3022
3023/* Check if lock codec is needed */
3024static pj_bool_t check_lock_codec(pjsua_call *call)
3025{
3026 const pjmedia_sdp_session *local_sdp, *remote_sdp;
3027 pj_bool_t has_mult_fmt = PJ_FALSE;
3028 unsigned i;
3029 pj_status_t status;
3030
3031 /* Check if lock codec is disabled */
3032 if (!pjsua_var.acc[call->acc_id].cfg.lock_codec)
3033 return PJ_FALSE;
3034
3035 /* Check lock codec retry count */
3036 if (call->lock_codec.retry_cnt >= LOCK_CODEC_MAX_RETRY)
3037 return PJ_FALSE;
3038
3039 /* Check if we are the answerer, we shouldn't need to lock codec */
3040 if (!call->inv->neg || !pjmedia_sdp_neg_was_answer_remote(call->inv->neg))
3041 return PJ_FALSE;
3042
3043 /* Check if remote answerer has given us more than one codecs. */
3044 status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &local_sdp);
3045 if (status != PJ_SUCCESS)
3046 return PJ_FALSE;
3047 status = pjmedia_sdp_neg_get_active_remote(call->inv->neg, &remote_sdp);
3048 if (status != PJ_SUCCESS)
3049 return PJ_FALSE;
3050
3051 for (i = 0; i < call->med_cnt && !has_mult_fmt; ++i) {
3052 pjsua_call_media *call_med = &call->media[i];
3053 const pjmedia_sdp_media *rem_m, *loc_m;
3054 unsigned codec_cnt = 0;
3055 unsigned j;
3056
3057 /* Skip this if the media is inactive or error */
3058 if (call_med->state == PJSUA_CALL_MEDIA_NONE ||
3059 call_med->state == PJSUA_CALL_MEDIA_ERROR ||
3060 call_med->dir == PJMEDIA_DIR_NONE)
3061 {
3062 continue;
3063 }
3064
3065 /* Remote may answer with less media lines. */
3066 if (i >= remote_sdp->media_count)
3067 continue;
3068
3069 rem_m = remote_sdp->media[i];
3070 loc_m = local_sdp->media[i];
3071
3072 /* Verify that media must be active. */
3073 pj_assert(loc_m->desc.port && rem_m->desc.port);
3074
3075 /* Count the formats in the answer. */
3076 for (j=0; j<rem_m->desc.fmt_count && codec_cnt <= 1; ++j) {
3077 if (!is_non_av_fmt(rem_m, &rem_m->desc.fmt[j]) && ++codec_cnt > 1)
3078 has_mult_fmt = PJ_TRUE;
3079 }
3080 }
3081
3082 /* Reset retry count when remote answer has one codec */
3083 if (!has_mult_fmt)
3084 call->lock_codec.retry_cnt = 0;
3085
3086 return has_mult_fmt;
3087}
3088
3089/* Check if ICE setup is complete and if it needs to send reinvite */
3090static pj_bool_t check_ice_complete(pjsua_call *call, pj_bool_t *need_reinv)
3091{
3092 pj_bool_t ice_need_reinv = PJ_FALSE;
3093 pj_bool_t ice_complete = PJ_TRUE;
3094 unsigned i;
3095
3096 /* Check if ICE setup is complete and if it needs reinvite */
3097 for (i = 0; i < call->med_cnt; ++i) {
3098 pjsua_call_media *call_med = &call->media[i];
3099 pjmedia_transport_info tpinfo;
3100 pjmedia_ice_transport_info *ice_info;
3101
3102 if (call_med->tp_st == PJSUA_MED_TP_NULL ||
3103 call_med->tp_st == PJSUA_MED_TP_DISABLED ||
3104 call_med->state == PJSUA_CALL_MEDIA_ERROR)
3105 {
3106 continue;
3107 }
3108
3109 pjmedia_transport_info_init(&tpinfo);
3110 pjmedia_transport_get_info(call_med->tp, &tpinfo);
3111 ice_info = (pjmedia_ice_transport_info*)
3112 pjmedia_transport_info_get_spc_info(
3113 &tpinfo, PJMEDIA_TRANSPORT_TYPE_ICE);
3114
3115 /* Check if ICE is active */
3116 if (!ice_info || !ice_info->active)
3117 continue;
3118
3119 /* Check if ICE setup not completed yet */
3120 if (ice_info->sess_state < PJ_ICE_STRANS_STATE_RUNNING) {
3121 ice_complete = PJ_FALSE;
3122 break;
3123 }
3124
3125 /* Check if ICE needs to send reinvite */
3126 if (!ice_need_reinv &&
3127 ice_info->sess_state == PJ_ICE_STRANS_STATE_RUNNING &&
3128 ice_info->role == PJ_ICE_SESS_ROLE_CONTROLLING)
3129 {
3130 pjsua_ice_config *cfg=&pjsua_var.acc[call->acc_id].cfg.ice_cfg;
3131 if ((cfg->ice_always_update && !call->reinv_ice_sent) ||
3132 pj_sockaddr_cmp(&tpinfo.sock_info.rtp_addr_name,
3133 &call_med->rtp_addr))
3134 {
3135 ice_need_reinv = PJ_TRUE;
3136 }
3137 }
3138 }
3139
3140 if (ice_complete && need_reinv)
3141 *need_reinv = ice_need_reinv;
3142
3143 return ice_complete;
3144}
3145
3146/* Check and send reinvite for lock codec and ICE update */
3147static pj_status_t process_pending_reinvite(pjsua_call *call)
3148{
3149 const pj_str_t ST_UPDATE = {"UPDATE", 6};
3150 pj_pool_t *pool = call->inv->pool_prov;
3151 pjsip_inv_session *inv = call->inv;
3152 pj_bool_t ice_need_reinv;
3153 pj_bool_t ice_completed;
3154 pj_bool_t need_lock_codec;
3155 pj_bool_t rem_can_update;
3156 pjmedia_sdp_session *new_offer;
3157 pjsip_tx_data *tdata;
3158 unsigned i;
3159 pj_status_t status;
3160
3161 /* Verify if another SDP negotiation is in progress, e.g: session timer
3162 * or another re-INVITE.
3163 */
3164 if (inv==NULL || inv->neg==NULL ||
3165 pjmedia_sdp_neg_get_state(inv->neg)!=PJMEDIA_SDP_NEG_STATE_DONE)
3166 {
3167 return PJMEDIA_SDPNEG_EINSTATE;
3168 }
3169
3170 /* Don't do this if call is disconnecting! */
3171 if (inv->state > PJSIP_INV_STATE_CONFIRMED || inv->cause >= 200)
3172 {
3173 return PJ_EINVALIDOP;
3174 }
3175
3176 /* Delay this when the SDP negotiation done in call state EARLY and
3177 * remote does not support UPDATE method.
3178 */
3179 if (inv->state == PJSIP_INV_STATE_EARLY &&
3180 pjsip_dlg_remote_has_cap(inv->dlg, PJSIP_H_ALLOW, NULL, &ST_UPDATE)!=
3181 PJSIP_DIALOG_CAP_SUPPORTED)
3182 {
3183 call->reinv_pending = PJ_TRUE;
3184 return PJ_EPENDING;
3185 }
3186
3187 /* Check if ICE setup is complete and if it needs reinvite */
3188 ice_completed = check_ice_complete(call, &ice_need_reinv);
3189 if (!ice_completed)
3190 return PJ_EPENDING;
3191
3192 /* Check if we need to lock codec */
3193 need_lock_codec = check_lock_codec(call);
3194
3195 /* Check if reinvite is really needed */
3196 if (!need_lock_codec && !ice_need_reinv)
3197 return PJ_SUCCESS;
3198
3199
3200 /* Okay! So we need to send re-INVITE/UPDATE */
3201
3202 /* Check if remote support UPDATE */
3203 rem_can_update = pjsip_dlg_remote_has_cap(inv->dlg, PJSIP_H_ALLOW, NULL,
3204 &ST_UPDATE) ==
3205 PJSIP_DIALOG_CAP_SUPPORTED;
3206
3207 /* Logging stuff */
3208 {
3209 const char *ST_ICE_UPDATE = "ICE transport address after "
3210 "ICE negotiation";
3211 const char *ST_LOCK_CODEC = "media session to use only one codec";
3212 PJ_LOG(4,(THIS_FILE, "Call %d sending %s for updating %s%s%s",
3213 call->index,
3214 (rem_can_update? "UPDATE" : "re-INVITE"),
3215 (ice_need_reinv? ST_ICE_UPDATE : ST_LOCK_CODEC),
3216 (ice_need_reinv && need_lock_codec? " and " : ""),
3217 (ice_need_reinv && need_lock_codec? ST_LOCK_CODEC : "")
3218 ));
3219 }
3220
3221 /* Generate SDP re-offer */
3222 status = pjsua_media_channel_create_sdp(call->index, pool, NULL,
3223 &new_offer, NULL);
3224 if (status != PJ_SUCCESS) {
3225 pjsua_perror(THIS_FILE, "Unable to create local SDP", status);
3226 return status;
3227 }
3228
3229 /* Update the new offer so it contains only a codec. Note that
3230 * SDP nego has removed unmatched codecs from the offer and the codec
3231 * order in the offer has been matched to the answer, so we'll override
3232 * the codecs in the just generated SDP with the ones from the active
3233 * local SDP and leave just one codec for the next SDP re-offer.
3234 */
3235 if (need_lock_codec) {
3236 const pjmedia_sdp_session *ref_sdp;
3237
3238 /* Get local active SDP as reference */
3239 status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &ref_sdp);
3240 if (status != PJ_SUCCESS)
3241 return status;
3242
3243 /* Verify media count. Note that remote may add/remove media line
3244 * in the answer. When answer has less media, it must have been
3245 * handled by pjsua_media_channel_update() as disabled media.
3246 * When answer has more media, it must have been ignored (treated
3247 * as non-exist) anywhere. Local media count should not be updated
3248 * at this point, as modifying media count operation (i.e: reinvite,
3249 * update, vid_set_strm) is currently blocking, protected with
3250 * dialog mutex, and eventually reset SDP nego state to LOCAL OFFER.
3251 */
3252 if (call->med_cnt != ref_sdp->media_count ||
3253 ref_sdp->media_count != new_offer->media_count)
3254 {
3255 /* Anyway, just in case, let's just return error */
3256 return PJMEDIA_SDPNEG_EINSTATE;
3257 }
3258
3259 for (i = 0; i < call->med_cnt; ++i) {
3260 unsigned j, codec_cnt = 0;
3261 const pjmedia_sdp_media *ref_m = ref_sdp->media[i];
3262 pjmedia_sdp_media *m = new_offer->media[i];
3263 pjsua_call_media *call_med = &call->media[i];
3264
3265 /* Verify if media is deactivated */
3266 if (call_med->state == PJSUA_CALL_MEDIA_NONE ||
3267 call_med->state == PJSUA_CALL_MEDIA_ERROR ||
3268 call_med->dir == PJMEDIA_DIR_NONE)
3269 {
3270 continue;
3271 }
3272
3273 /* Reset formats */
3274 m->desc.fmt_count = 0;
3275 pjmedia_sdp_attr_remove_all(&m->attr_count, m->attr, "rtpmap");
3276 pjmedia_sdp_attr_remove_all(&m->attr_count, m->attr, "fmtp");
3277
3278 /* Copy only the first format + any non-AV formats from
3279 * the active local SDP.
3280 */
3281 for (j = 0; j < ref_m->desc.fmt_count; ++j) {
3282 const pj_str_t *fmt = &ref_m->desc.fmt[j];
3283
3284 if (is_non_av_fmt(ref_m, fmt) || (++codec_cnt == 1)) {
3285 pjmedia_sdp_attr *a;
3286
3287 m->desc.fmt[m->desc.fmt_count++] = *fmt;
3288 a = pjmedia_sdp_attr_find2(ref_m->attr_count, ref_m->attr,
3289 "rtpmap", fmt);
3290 if (a) pjmedia_sdp_attr_add(&m->attr_count, m->attr, a);
3291 a = pjmedia_sdp_attr_find2(ref_m->attr_count, ref_m->attr,
3292 "fmtp", fmt);
3293 if (a) pjmedia_sdp_attr_add(&m->attr_count, m->attr, a);
3294 }
3295 }
3296 }
3297 }
3298
3299 /* Put back original direction and "c=0.0.0.0" line */
3300 {
3301 const pjmedia_sdp_session *cur_sdp;
3302
3303 /* Get local active SDP */
3304 status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &cur_sdp);
3305 if (status != PJ_SUCCESS)
3306 return status;
3307
3308 /* Make sure media count has not been changed */
3309 if (call->med_cnt != cur_sdp->media_count)
3310 return PJMEDIA_SDPNEG_EINSTATE;
3311
3312 for (i = 0; i < call->med_cnt; ++i) {
3313 const pjmedia_sdp_media *m = cur_sdp->media[i];
3314 pjmedia_sdp_media *new_m = new_offer->media[i];
3315 pjsua_call_media *call_med = &call->media[i];
3316 pjmedia_sdp_attr *a = NULL;
3317
3318 /* Update direction to the current dir */
3319 pjmedia_sdp_media_remove_all_attr(new_m, "sendrecv");
3320 pjmedia_sdp_media_remove_all_attr(new_m, "sendonly");
3321 pjmedia_sdp_media_remove_all_attr(new_m, "recvonly");
3322 pjmedia_sdp_media_remove_all_attr(new_m, "inactive");
3323
3324 if (call_med->dir == PJMEDIA_DIR_ENCODING_DECODING) {
3325 a = pjmedia_sdp_attr_create(pool, "sendrecv", NULL);
3326 } else if (call_med->dir == PJMEDIA_DIR_ENCODING) {
3327 a = pjmedia_sdp_attr_create(pool, "sendonly", NULL);
3328 } else if (call_med->dir == PJMEDIA_DIR_DECODING) {
3329 a = pjmedia_sdp_attr_create(pool, "recvonly", NULL);
3330 } else {
3331 const pjmedia_sdp_conn *conn;
3332 a = pjmedia_sdp_attr_create(pool, "inactive", NULL);
3333
3334 /* Also check if the original c= line address is zero */
3335 conn = m->conn;
3336 if (!conn)
3337 conn = cur_sdp->conn;
3338 if (pj_strcmp2(&conn->addr, "0.0.0.0")==0 ||
3339 pj_strcmp2(&conn->addr, "0")==0)
3340 {
3341 if (!new_m->conn) {
3342 new_m->conn = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_conn);
3343 }
3344
3345 if (pj_strcmp2(&new_m->conn->addr, "0.0.0.0")) {
3346 new_m->conn->net_type = pj_str("IN");
3347 new_m->conn->addr_type = pj_str("IP4");
3348 new_m->conn->addr = pj_str("0.0.0.0");
3349 }
3350 }
3351 }
3352
3353 pj_assert(a);
3354 pjmedia_sdp_media_add_attr(new_m, a);
3355 }
3356 }
3357
3358
3359 if (rem_can_update) {
3360 status = pjsip_inv_update(inv, NULL, new_offer, &tdata);
3361 } else {
3362 status = pjsip_inv_reinvite(inv, NULL, new_offer, &tdata);
3363 }
3364
3365 if (status==PJ_EINVALIDOP &&
3366 ++call->lock_codec.retry_cnt < LOCK_CODEC_MAX_RETRY)
3367 {
3368 /* Ups, let's reschedule again */
3369 pjsua_call_schedule_reinvite_check(call, LOCK_CODEC_RETRY_INTERVAL);
3370 return PJ_SUCCESS;
3371 } else if (status != PJ_SUCCESS) {
3372 pjsua_perror(THIS_FILE, "Error creating UPDATE/re-INVITE",
3373 status);
3374 return status;
3375 }
3376
3377 /* Send the UPDATE/re-INVITE request */
3378 status = pjsip_inv_send_msg(inv, tdata);
3379 if (status != PJ_SUCCESS) {
3380 pjsua_perror(THIS_FILE, "Error sending UPDATE/re-INVITE",
3381 status);
3382 return status;
3383 }
3384
3385 /* Update flags */
3386 if (ice_need_reinv)
3387 call->reinv_ice_sent = PJ_TRUE;
3388 if (need_lock_codec)
3389 ++call->lock_codec.retry_cnt;
3390
3391 return PJ_SUCCESS;
3392}
3393
3394
3395/*
3396 * This callback receives notification from invite session when the
3397 * session state has changed.
3398 */
3399static void pjsua_call_on_state_changed(pjsip_inv_session *inv,
3400 pjsip_event *e)
3401{
3402 pjsua_call *call;
3403
3404 pj_log_push_indent();
3405
3406 call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id];
3407
3408 if (!call) {
3409 pj_log_pop_indent();
3410 return;
3411 }
3412
3413
3414 /* Get call times */
3415 switch (inv->state) {
3416 case PJSIP_INV_STATE_EARLY:
3417 case PJSIP_INV_STATE_CONNECTING:
3418 if (call->res_time.sec == 0)
3419 pj_gettimeofday(&call->res_time);
3420 call->last_code = (pjsip_status_code)
3421 e->body.tsx_state.tsx->status_code;
3422 pj_strncpy(&call->last_text,
3423 &e->body.tsx_state.tsx->status_text,
3424 sizeof(call->last_text_buf_));
3425 break;
3426 case PJSIP_INV_STATE_CONFIRMED:
3427 pj_gettimeofday(&call->conn_time);
3428
3429 /* See if auto reinvite was pended as media update was done in the
3430 * EARLY state and remote does not support UPDATE.
3431 */
3432 if (call->reinv_pending) {
3433 call->reinv_pending = PJ_FALSE;
3434 pjsua_call_schedule_reinvite_check(call, 0);
3435 }
3436 break;
3437 case PJSIP_INV_STATE_DISCONNECTED:
3438 pj_gettimeofday(&call->dis_time);
3439 if (call->res_time.sec == 0)
3440 pj_gettimeofday(&call->res_time);
3441 if (e->type == PJSIP_EVENT_TSX_STATE &&
3442 e->body.tsx_state.tsx->status_code > call->last_code)
3443 {
3444 call->last_code = (pjsip_status_code)
3445 e->body.tsx_state.tsx->status_code;
3446 pj_strncpy(&call->last_text,
3447 &e->body.tsx_state.tsx->status_text,
3448 sizeof(call->last_text_buf_));
3449 } else {
3450 call->last_code = PJSIP_SC_REQUEST_TERMINATED;
3451 pj_strncpy(&call->last_text,
3452 pjsip_get_status_text(call->last_code),
3453 sizeof(call->last_text_buf_));
3454 }
3455
3456 /* Stop reinvite timer, if it is active */
3457 if (call->reinv_timer.id) {
3458 pjsua_cancel_timer(&call->reinv_timer);
3459 call->reinv_timer.id = PJ_FALSE;
3460 }
3461 break;
3462 default:
3463 call->last_code = (pjsip_status_code)
3464 e->body.tsx_state.tsx->status_code;
3465 pj_strncpy(&call->last_text,
3466 &e->body.tsx_state.tsx->status_text,
3467 sizeof(call->last_text_buf_));
3468 break;
3469 }
3470
3471 /* If this is an outgoing INVITE that was created because of
3472 * REFER/transfer, send NOTIFY to transferer.
3473 */
3474 if (call->xfer_sub && e->type==PJSIP_EVENT_TSX_STATE) {
3475 int st_code = -1;
3476 pjsip_evsub_state ev_state = PJSIP_EVSUB_STATE_ACTIVE;
3477
3478
3479 switch (call->inv->state) {
3480 case PJSIP_INV_STATE_NULL:
3481 case PJSIP_INV_STATE_CALLING:
3482 /* Do nothing */
3483 break;
3484
3485 case PJSIP_INV_STATE_EARLY:
3486 case PJSIP_INV_STATE_CONNECTING:
3487 st_code = e->body.tsx_state.tsx->status_code;
3488 if (call->inv->state == PJSIP_INV_STATE_CONNECTING)
3489 ev_state = PJSIP_EVSUB_STATE_TERMINATED;
3490 else
3491 ev_state = PJSIP_EVSUB_STATE_ACTIVE;
3492 break;
3493
3494 case PJSIP_INV_STATE_CONFIRMED:
3495#if 0
3496/* We don't need this, as we've terminated the subscription in
3497 * CONNECTING state.
3498 */
3499 /* When state is confirmed, send the final 200/OK and terminate
3500 * subscription.
3501 */
3502 st_code = e->body.tsx_state.tsx->status_code;
3503 ev_state = PJSIP_EVSUB_STATE_TERMINATED;
3504#endif
3505 break;
3506
3507 case PJSIP_INV_STATE_DISCONNECTED:
3508 st_code = e->body.tsx_state.tsx->status_code;
3509 ev_state = PJSIP_EVSUB_STATE_TERMINATED;
3510 break;
3511
3512 case PJSIP_INV_STATE_INCOMING:
3513 /* Nothing to do. Just to keep gcc from complaining about
3514 * unused enums.
3515 */
3516 break;
3517 }
3518
3519 if (st_code != -1) {
3520 pjsip_tx_data *tdata;
3521 pj_status_t status;
3522
3523 status = pjsip_xfer_notify( call->xfer_sub,
3524 ev_state, st_code,
3525 NULL, &tdata);
3526 if (status != PJ_SUCCESS) {
3527 pjsua_perror(THIS_FILE, "Unable to create NOTIFY", status);
3528 } else {
3529 status = pjsip_xfer_send_request(call->xfer_sub, tdata);
3530 if (status != PJ_SUCCESS) {
3531 pjsua_perror(THIS_FILE, "Unable to send NOTIFY", status);
3532 }
3533 }
3534 }
3535 }
3536
3537 /* Ticket #1627: Invoke on_call_tsx_state() when call is disconnected. */
3538 if (inv->state == PJSIP_INV_STATE_DISCONNECTED &&
3539 e->type == PJSIP_EVENT_TSX_STATE &&
3540 call->inv &&
3541 pjsua_var.ua_cfg.cb.on_call_tsx_state)
3542 {
3543 (*pjsua_var.ua_cfg.cb.on_call_tsx_state)(call->index,
3544 e->body.tsx_state.tsx, e);
3545 }
3546
3547 if (pjsua_var.ua_cfg.cb.on_call_state)
3548 (*pjsua_var.ua_cfg.cb.on_call_state)(call->index, e);
3549
3550 /* call->inv may be NULL now */
3551
3552 /* Destroy media session when invite session is disconnected. */
3553 if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
3554
3555 PJSUA_LOCK();
3556
3557 pjsua_media_channel_deinit(call->index);
3558
3559 /* Free call */
3560 call->inv = NULL;
3561
3562 pj_assert(pjsua_var.call_cnt > 0);
3563 --pjsua_var.call_cnt;
3564
3565 /* Reset call */
3566 reset_call(call->index);
3567
3568 pjsua_check_snd_dev_idle();
3569
3570 PJSUA_UNLOCK();
3571 }
3572 pj_log_pop_indent();
3573}
3574
3575/*
3576 * This callback is called by invite session framework when UAC session
3577 * has forked.
3578 */
3579static void pjsua_call_on_forked( pjsip_inv_session *inv,
3580 pjsip_event *e)
3581{
3582 PJ_UNUSED_ARG(inv);
3583 PJ_UNUSED_ARG(e);
3584
3585 PJ_TODO(HANDLE_FORKED_DIALOG);
3586}
3587
3588
3589/*
3590 * Callback from UA layer when forked dialog response is received.
3591 */
3592pjsip_dialog* on_dlg_forked(pjsip_dialog *dlg, pjsip_rx_data *res)
3593{
3594 if (dlg->uac_has_2xx &&
3595 res->msg_info.cseq->method.id == PJSIP_INVITE_METHOD &&
3596 pjsip_rdata_get_tsx(res) == NULL &&
3597 res->msg_info.msg->line.status.code/100 == 2)
3598 {
3599 pjsip_dialog *forked_dlg;
3600 pjsip_tx_data *bye;
3601 pj_status_t status;
3602
3603 /* Create forked dialog */
3604 status = pjsip_dlg_fork(dlg, res, &forked_dlg);
3605 if (status != PJ_SUCCESS)
3606 return NULL;
3607
3608 pjsip_dlg_inc_lock(forked_dlg);
3609
3610 /* Disconnect the call */
3611 status = pjsip_dlg_create_request(forked_dlg, &pjsip_bye_method,
3612 -1, &bye);
3613 if (status == PJ_SUCCESS) {
3614 status = pjsip_dlg_send_request(forked_dlg, bye, -1, NULL);
3615 }
3616
3617 pjsip_dlg_dec_lock(forked_dlg);
3618
3619 if (status != PJ_SUCCESS) {
3620 return NULL;
3621 }
3622
3623 return forked_dlg;
3624
3625 } else {
3626 return dlg;
3627 }
3628}
3629
3630/*
3631 * Disconnect call upon error.
3632 */
3633static void call_disconnect( pjsip_inv_session *inv,
3634 int code )
3635{
3636 pjsua_call *call;
3637 pjsip_tx_data *tdata;
3638 pj_status_t status;
3639
3640 call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id];
3641
3642 status = pjsip_inv_end_session(inv, code, NULL, &tdata);
3643 if (status != PJ_SUCCESS)
3644 return;
3645
3646 /* Add SDP in 488 status */
3647#if DISABLED_FOR_TICKET_1185
3648 if (call && call->tp && tdata->msg->type==PJSIP_RESPONSE_MSG &&
3649 code==PJSIP_SC_NOT_ACCEPTABLE_HERE)
3650 {
3651 pjmedia_sdp_session *local_sdp;
3652 pjmedia_transport_info ti;
3653
3654 pjmedia_transport_info_init(&ti);
3655 pjmedia_transport_get_info(call->med_tp, &ti);
3656 status = pjmedia_endpt_create_sdp(pjsua_var.med_endpt, tdata->pool,
3657 1, &ti.sock_info, &local_sdp);
3658 if (status == PJ_SUCCESS) {
3659 pjsip_create_sdp_body(tdata->pool, local_sdp,
3660 &tdata->msg->body);
3661 }
3662 }
3663#endif
3664
3665 pjsip_inv_send_msg(inv, tdata);
3666}
3667
3668/*
3669 * Callback to be called when SDP offer/answer negotiation has just completed
3670 * in the session. This function will start/update media if negotiation
3671 * has succeeded.
3672 */
3673static void pjsua_call_on_media_update(pjsip_inv_session *inv,
3674 pj_status_t status)
3675{
3676 pjsua_call *call;
3677 const pjmedia_sdp_session *local_sdp;
3678 const pjmedia_sdp_session *remote_sdp;
3679 //const pj_str_t st_update = {"UPDATE", 6};
3680
3681 pj_log_push_indent();
3682
3683 call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id];
3684
3685 if (status != PJ_SUCCESS) {
3686
3687 pjsua_perror(THIS_FILE, "SDP negotiation has failed", status);
3688
3689 /* Clean up provisional media */
3690 pjsua_media_prov_clean_up(call->index);
3691
3692 /* Do not deinitialize media since this may be a re-INVITE or
3693 * UPDATE (which in this case the media should not get affected
3694 * by the failed re-INVITE/UPDATE). The media will be shutdown
3695 * when call is disconnected anyway.
3696 */
3697 /* Stop/destroy media, if any */
3698 /*pjsua_media_channel_deinit(call->index);*/
3699
3700 /* Disconnect call if we're not in the middle of initializing an
3701 * UAS dialog and if this is not a re-INVITE
3702 */
3703 if (inv->state != PJSIP_INV_STATE_NULL &&
3704 inv->state != PJSIP_INV_STATE_CONFIRMED)
3705 {
3706 call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE);
3707 }
3708
3709 goto on_return;
3710 }
3711
3712
3713 /* Get local and remote SDP */
3714 status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &local_sdp);
3715 if (status != PJ_SUCCESS) {
3716 pjsua_perror(THIS_FILE,
3717 "Unable to retrieve currently active local SDP",
3718 status);
3719 //call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE);
3720 goto on_return;
3721 }
3722
3723 status = pjmedia_sdp_neg_get_active_remote(call->inv->neg, &remote_sdp);
3724 if (status != PJ_SUCCESS) {
3725 pjsua_perror(THIS_FILE,
3726 "Unable to retrieve currently active remote SDP",
3727 status);
3728 //call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE);
3729 goto on_return;
3730 }
3731
3732 /* Update remote's NAT type */
3733 if (pjsua_var.ua_cfg.nat_type_in_sdp) {
3734 update_remote_nat_type(call, remote_sdp);
3735 }
3736
3737 /* Update media channel with the new SDP */
3738 status = pjsua_media_channel_update(call->index, local_sdp, remote_sdp);
3739 if (status != PJ_SUCCESS) {
3740 pjsua_perror(THIS_FILE, "Unable to create media session",
3741 status);
3742 call_disconnect(inv, PJSIP_SC_NOT_ACCEPTABLE_HERE);
3743 /* No need to deinitialize; media will be shutdown when call
3744 * state is disconnected anyway.
3745 */
3746 /*pjsua_media_channel_deinit(call->index);*/
3747 goto on_return;
3748 }
3749
3750 /* Ticket #476: make sure only one codec is specified in the answer. */
3751 pjsua_call_schedule_reinvite_check(call, 0);
3752
3753 /* Call application callback, if any */
3754 if (pjsua_var.ua_cfg.cb.on_call_media_state)
3755 pjsua_var.ua_cfg.cb.on_call_media_state(call->index);
3756
3757on_return:
3758 pj_log_pop_indent();
3759}
3760
3761
3762/* Modify SDP for call hold. */
3763static pj_status_t modify_sdp_of_call_hold(pjsua_call *call,
3764 pj_pool_t *pool,
3765 pjmedia_sdp_session *sdp,
3766 pj_bool_t as_answerer)
3767{
3768 unsigned mi;
3769
3770 /* Call-hold is done by set the media direction to 'sendonly'
3771 * (PJMEDIA_DIR_ENCODING), except when current media direction is
3772 * 'inactive' (PJMEDIA_DIR_NONE).
3773 * (See RFC 3264 Section 8.4 and RFC 4317 Section 3.1)
3774 */
3775 /* http://trac.pjsip.org/repos/ticket/880
3776 if (call->dir != PJMEDIA_DIR_ENCODING) {
3777 */
3778 /* https://trac.pjsip.org/repos/ticket/1142:
3779 * configuration to use c=0.0.0.0 for call hold.
3780 */
3781
3782 for (mi=0; mi<sdp->media_count; ++mi) {
3783 pjmedia_sdp_media *m = sdp->media[mi];
3784
3785 if (call->call_hold_type == PJSUA_CALL_HOLD_TYPE_RFC2543) {
3786 pjmedia_sdp_conn *conn;
3787 pjmedia_sdp_attr *attr;
3788
3789 /* Get SDP media connection line */
3790 conn = m->conn;
3791 if (!conn)
3792 conn = sdp->conn;
3793
3794 /* Modify address */
3795 conn->addr = pj_str("0.0.0.0");
3796
3797 /* Remove existing directions attributes */
3798 pjmedia_sdp_media_remove_all_attr(m, "sendrecv");
3799 pjmedia_sdp_media_remove_all_attr(m, "sendonly");
3800 pjmedia_sdp_media_remove_all_attr(m, "recvonly");
3801 pjmedia_sdp_media_remove_all_attr(m, "inactive");
3802
3803 /* Add inactive attribute */
3804 attr = pjmedia_sdp_attr_create(pool, "inactive", NULL);
3805 pjmedia_sdp_media_add_attr(m, attr);
3806
3807
3808 } else {
3809 pjmedia_sdp_attr *attr;
3810
3811 /* Remove existing directions attributes */
3812 pjmedia_sdp_media_remove_all_attr(m, "sendrecv");
3813 pjmedia_sdp_media_remove_all_attr(m, "sendonly");
3814 pjmedia_sdp_media_remove_all_attr(m, "recvonly");
3815 pjmedia_sdp_media_remove_all_attr(m, "inactive");
3816
3817 /* When as answerer, just simply set dir to "sendonly", note that
3818 * if the offer uses "sendonly" or "inactive", the SDP negotiator
3819 * will change our answer dir to "inactive".
3820 */
3821 if (as_answerer || (call->media[mi].dir & PJMEDIA_DIR_ENCODING)) {
3822 /* Add sendonly attribute */
3823 attr = pjmedia_sdp_attr_create(pool, "sendonly", NULL);
3824 pjmedia_sdp_media_add_attr(m, attr);
3825 } else {
3826 /* Add inactive attribute */
3827 attr = pjmedia_sdp_attr_create(pool, "inactive", NULL);
3828 pjmedia_sdp_media_add_attr(m, attr);
3829 }
3830 }
3831 }
3832
3833 return PJ_SUCCESS;
3834}
3835
3836/* Create SDP for call hold. */
3837static pj_status_t create_sdp_of_call_hold(pjsua_call *call,
3838 pjmedia_sdp_session **p_sdp)
3839{
3840 pj_status_t status;
3841 pj_pool_t *pool;
3842 pjmedia_sdp_session *sdp;
3843
3844 /* Use call's provisional pool */
3845 pool = call->inv->pool_prov;
3846
3847 /* Create new offer */
3848 status = pjsua_media_channel_create_sdp(call->index, pool, NULL, &sdp,
3849 NULL);
3850 if (status != PJ_SUCCESS) {
3851 pjsua_perror(THIS_FILE, "Unable to create local SDP", status);
3852 return status;
3853 }
3854
3855 status = modify_sdp_of_call_hold(call, pool, sdp, PJ_FALSE);
3856 if (status != PJ_SUCCESS)
3857 return status;
3858
3859 *p_sdp = sdp;
3860
3861 return PJ_SUCCESS;
3862}
3863
3864/*
3865 * Called when session received new offer.
3866 */
3867static void pjsua_call_on_rx_offer(pjsip_inv_session *inv,
3868 const pjmedia_sdp_session *offer)
3869{
3870 pjsua_call *call;
3871 pjmedia_sdp_session *answer;
3872 unsigned i;
3873 pj_status_t status;
3874
3875 call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id];
3876
3877 /* Supply candidate answer */
3878 PJ_LOG(4,(THIS_FILE, "Call %d: received updated media offer",
3879 call->index));
3880 pj_log_push_indent();
3881
3882 if (pjsua_var.ua_cfg.cb.on_call_rx_offer) {
3883 pjsip_status_code code = PJSIP_SC_OK;
3884 pjsua_call_setting opt = call->opt;
3885
3886 (*pjsua_var.ua_cfg.cb.on_call_rx_offer)(call->index, offer, NULL,
3887 &code, &opt);
3888
3889 if (code != PJSIP_SC_OK) {
3890 PJ_LOG(4,(THIS_FILE, "Rejecting updated media offer on call %d",
3891 call->index));
3892 goto on_return;
3893 }
3894
3895 call->opt = opt;
3896 }
3897
3898 /* Re-init media for the new remote offer before creating SDP */
3899 status = apply_call_setting(call, &call->opt, offer);
3900 if (status != PJ_SUCCESS)
3901 goto on_return;
3902
3903 status = pjsua_media_channel_create_sdp(call->index,
3904 call->inv->pool_prov,
3905 offer, &answer, NULL);
3906 if (status != PJ_SUCCESS) {
3907 pjsua_perror(THIS_FILE, "Unable to create local SDP", status);
3908 goto on_return;
3909 }
3910
3911 /* Validate media count in the generated answer */
3912 pj_assert(answer->media_count == offer->media_count);
3913
3914 /* Check if offer's conn address is zero */
3915 for (i = 0; i < answer->media_count; ++i) {
3916 pjmedia_sdp_conn *conn;
3917
3918 conn = offer->media[i]->conn;
3919 if (!conn)
3920 conn = offer->conn;
3921
3922 if (pj_strcmp2(&conn->addr, "0.0.0.0")==0 ||
3923 pj_strcmp2(&conn->addr, "0")==0)
3924 {
3925 pjmedia_sdp_conn *a_conn = answer->media[i]->conn;
3926
3927 /* Modify answer address */
3928 if (a_conn) {
3929 a_conn->addr = pj_str("0.0.0.0");
3930 } else if (answer->conn == NULL ||
3931 pj_strcmp2(&answer->conn->addr, "0.0.0.0") != 0)
3932 {
3933 a_conn = PJ_POOL_ZALLOC_T(call->inv->pool_prov,
3934 pjmedia_sdp_conn);
3935 a_conn->net_type = pj_str("IN");
3936 a_conn->addr_type = pj_str("IP4");
3937 a_conn->addr = pj_str("0.0.0.0");
3938 answer->media[i]->conn = a_conn;
3939 }
3940 }
3941 }
3942
3943 /* Check if call is on-hold */
3944 if (call->local_hold) {
3945 modify_sdp_of_call_hold(call, call->inv->pool_prov, answer, PJ_TRUE);
3946 }
3947
3948 status = pjsip_inv_set_sdp_answer(call->inv, answer);
3949 if (status != PJ_SUCCESS) {
3950 pjsua_perror(THIS_FILE, "Unable to set answer", status);
3951 goto on_return;
3952 }
3953
3954on_return:
3955 pj_log_pop_indent();
3956}
3957
3958
3959/*
3960 * Called to generate new offer.
3961 */
3962static void pjsua_call_on_create_offer(pjsip_inv_session *inv,
3963 pjmedia_sdp_session **offer)
3964{
3965 pjsua_call *call;
3966 pj_status_t status;
3967
3968 pj_log_push_indent();
3969
3970 call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id];
3971
3972 /* See if we've put call on hold. */
3973 if (call->local_hold) {
3974 PJ_LOG(4,(THIS_FILE,
3975 "Call %d: call is on-hold locally, creating call-hold SDP ",
3976 call->index));
3977 status = create_sdp_of_call_hold( call, offer );
3978 } else {
3979 PJ_LOG(4,(THIS_FILE, "Call %d: asked to send a new offer",
3980 call->index));
3981
3982 status = pjsua_media_channel_create_sdp(call->index,
3983 call->inv->pool_prov,
3984 NULL, offer, NULL);
3985 }
3986
3987 if (status != PJ_SUCCESS) {
3988 pjsua_perror(THIS_FILE, "Unable to create local SDP", status);
3989 goto on_return;
3990 }
3991
3992on_return:
3993 pj_log_pop_indent();
3994}
3995
3996
3997/*
3998 * Callback called by event framework when the xfer subscription state
3999 * has changed.
4000 */
4001static void xfer_client_on_evsub_state( pjsip_evsub *sub, pjsip_event *event)
4002{
4003
4004 PJ_UNUSED_ARG(event);
4005
4006 pj_log_push_indent();
4007
4008 /*
4009 * When subscription is accepted (got 200/OK to REFER), check if
4010 * subscription suppressed.
4011 */
4012 if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_ACCEPTED) {
4013
4014 pjsip_rx_data *rdata;
4015 pjsip_generic_string_hdr *refer_sub;
4016 const pj_str_t REFER_SUB = { "Refer-Sub", 9 };
4017 pjsua_call *call;
4018
4019 call = (pjsua_call*) pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id);
4020
4021 /* Must be receipt of response message */
4022 pj_assert(event->type == PJSIP_EVENT_TSX_STATE &&
4023 event->body.tsx_state.type == PJSIP_EVENT_RX_MSG);
4024 rdata = event->body.tsx_state.src.rdata;
4025
4026 /* Find Refer-Sub header */
4027 refer_sub = (pjsip_generic_string_hdr*)
4028 pjsip_msg_find_hdr_by_name(rdata->msg_info.msg,
4029 &REFER_SUB, NULL);
4030
4031 /* Check if subscription is suppressed */
4032 if (refer_sub && pj_stricmp2(&refer_sub->hvalue, "false")==0) {
4033 /* Since no subscription is desired, assume that call has been
4034 * transfered successfully.
4035 */
4036 if (call && pjsua_var.ua_cfg.cb.on_call_transfer_status) {
4037 const pj_str_t ACCEPTED = { "Accepted", 8 };
4038 pj_bool_t cont = PJ_FALSE;
4039 (*pjsua_var.ua_cfg.cb.on_call_transfer_status)(call->index,
4040 200,
4041 &ACCEPTED,
4042 PJ_TRUE,
4043 &cont);
4044 }
4045
4046 /* Yes, subscription is suppressed.
4047 * Terminate our subscription now.
4048 */
4049 PJ_LOG(4,(THIS_FILE, "Xfer subscription suppressed, terminating "
4050 "event subcription..."));
4051 pjsip_evsub_terminate(sub, PJ_TRUE);
4052
4053 } else {
4054 /* Notify application about call transfer progress.
4055 * Initially notify with 100/Accepted status.
4056 */
4057 if (call && pjsua_var.ua_cfg.cb.on_call_transfer_status) {
4058 const pj_str_t ACCEPTED = { "Accepted", 8 };
4059 pj_bool_t cont = PJ_FALSE;
4060 (*pjsua_var.ua_cfg.cb.on_call_transfer_status)(call->index,
4061 100,
4062 &ACCEPTED,
4063 PJ_FALSE,
4064 &cont);
4065 }
4066 }
4067 }
4068 /*
4069 * On incoming NOTIFY, notify application about call transfer progress.
4070 */
4071 else if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_ACTIVE ||
4072 pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED)
4073 {
4074 pjsua_call *call;
4075 pjsip_msg *msg;
4076 pjsip_msg_body *body;
4077 pjsip_status_line status_line;
4078 pj_bool_t is_last;
4079 pj_bool_t cont;
4080 pj_status_t status;
4081
4082 call = (pjsua_call*) pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id);
4083
4084 /* When subscription is terminated, clear the xfer_sub member of
4085 * the inv_data.
4086 */
4087 if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) {
4088 pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, NULL);
4089 PJ_LOG(4,(THIS_FILE, "Xfer client subscription terminated"));
4090
4091 }
4092
4093 if (!call || !event || !pjsua_var.ua_cfg.cb.on_call_transfer_status) {
4094 /* Application is not interested with call progress status */
4095 goto on_return;
4096 }
4097
4098 /* This better be a NOTIFY request */
4099 if (event->type == PJSIP_EVENT_TSX_STATE &&
4100 event->body.tsx_state.type == PJSIP_EVENT_RX_MSG)
4101 {
4102 pjsip_rx_data *rdata;
4103
4104 rdata = event->body.tsx_state.src.rdata;
4105
4106 /* Check if there's body */
4107 msg = rdata->msg_info.msg;
4108 body = msg->body;
4109 if (!body) {
4110 PJ_LOG(2,(THIS_FILE,
4111 "Warning: received NOTIFY without message body"));
4112 goto on_return;
4113 }
4114
4115 /* Check for appropriate content */
4116 if (pj_stricmp2(&body->content_type.type, "message") != 0 ||
4117 pj_stricmp2(&body->content_type.subtype, "sipfrag") != 0)
4118 {
4119 PJ_LOG(2,(THIS_FILE,
4120 "Warning: received NOTIFY with non message/sipfrag "
4121 "content"));
4122 goto on_return;
4123 }
4124
4125 /* Try to parse the content */
4126 status = pjsip_parse_status_line((char*)body->data, body->len,
4127 &status_line);
4128 if (status != PJ_SUCCESS) {
4129 PJ_LOG(2,(THIS_FILE,
4130 "Warning: received NOTIFY with invalid "
4131 "message/sipfrag content"));
4132 goto on_return;
4133 }
4134
4135 } else {
4136 status_line.code = 500;
4137 status_line.reason = *pjsip_get_status_text(500);
4138 }
4139
4140 /* Notify application */
4141 is_last = (pjsip_evsub_get_state(sub)==PJSIP_EVSUB_STATE_TERMINATED);
4142 cont = !is_last;
4143 (*pjsua_var.ua_cfg.cb.on_call_transfer_status)(call->index,
4144 status_line.code,
4145 &status_line.reason,
4146 is_last, &cont);
4147
4148 if (!cont) {
4149 pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, NULL);
4150 }
4151
4152 /* If the call transfer has completed but the subscription is
4153 * not terminated, terminate it now.
4154 */
4155 if (status_line.code/100 == 2 && !is_last) {
4156 pjsip_tx_data *tdata;
4157
4158 status = pjsip_evsub_initiate(sub, &pjsip_subscribe_method,
4159 0, &tdata);
4160 if (status == PJ_SUCCESS)
4161 status = pjsip_evsub_send_request(sub, tdata);
4162 }
4163 }
4164
4165on_return:
4166 pj_log_pop_indent();
4167}
4168
4169
4170/*
4171 * Callback called by event framework when the xfer subscription state
4172 * has changed.
4173 */
4174static void xfer_server_on_evsub_state( pjsip_evsub *sub, pjsip_event *event)
4175{
4176 PJ_UNUSED_ARG(event);
4177
4178 pj_log_push_indent();
4179
4180 /*
4181 * When subscription is terminated, clear the xfer_sub member of
4182 * the inv_data.
4183 */
4184 if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) {
4185 pjsua_call *call;
4186
4187 call = (pjsua_call*) pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id);
4188 if (!call)
4189 goto on_return;
4190
4191 pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, NULL);
4192 call->xfer_sub = NULL;
4193
4194 PJ_LOG(4,(THIS_FILE, "Xfer server subscription terminated"));
4195 }
4196
4197on_return:
4198 pj_log_pop_indent();
4199}
4200
4201
4202/*
4203 * Follow transfer (REFER) request.
4204 */
4205static void on_call_transfered( pjsip_inv_session *inv,
4206 pjsip_rx_data *rdata )
4207{
4208 pj_status_t status;
4209 pjsip_tx_data *tdata;
4210 pjsua_call *existing_call;
4211 int new_call;
4212 const pj_str_t str_refer_to = { "Refer-To", 8};
4213 const pj_str_t str_refer_sub = { "Refer-Sub", 9 };
4214 const pj_str_t str_ref_by = { "Referred-By", 11 };
4215 pjsip_generic_string_hdr *refer_to;
4216 pjsip_generic_string_hdr *refer_sub;
4217 pjsip_hdr *ref_by_hdr;
4218 pj_bool_t no_refer_sub = PJ_FALSE;
4219 char *uri;
4220 pjsua_msg_data msg_data;
4221 pj_str_t tmp;
4222 pjsip_status_code code;
4223 pjsip_evsub *sub;
4224 pjsua_call_setting call_opt;
4225
4226 pj_log_push_indent();
4227
4228 existing_call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id];
4229
4230 /* Find the Refer-To header */
4231 refer_to = (pjsip_generic_string_hdr*)
4232 pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_refer_to, NULL);
4233
4234 if (refer_to == NULL) {
4235 /* Invalid Request.
4236 * No Refer-To header!
4237 */
4238 PJ_LOG(4,(THIS_FILE, "Received REFER without Refer-To header!"));
4239 pjsip_dlg_respond( inv->dlg, rdata, 400, NULL, NULL, NULL);
4240 goto on_return;
4241 }
4242
4243 /* Find optional Refer-Sub header */
4244 refer_sub = (pjsip_generic_string_hdr*)
4245 pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_refer_sub, NULL);
4246
4247 if (refer_sub) {
4248 if (!pj_strnicmp2(&refer_sub->hvalue, "true", 4)==0)
4249 no_refer_sub = PJ_TRUE;
4250 }
4251
4252 /* Find optional Referred-By header (to be copied onto outgoing INVITE
4253 * request.
4254 */
4255 ref_by_hdr = (pjsip_hdr*)
4256 pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_ref_by,
4257 NULL);
4258
4259 /* Notify callback */
4260 code = PJSIP_SC_ACCEPTED;
4261 if (pjsua_var.ua_cfg.cb.on_call_transfer_request) {
4262 (*pjsua_var.ua_cfg.cb.on_call_transfer_request)(existing_call->index,
4263 &refer_to->hvalue,
4264 &code);
4265 }
4266
4267 call_opt = existing_call->opt;
4268 if (pjsua_var.ua_cfg.cb.on_call_transfer_request2) {
4269 (*pjsua_var.ua_cfg.cb.on_call_transfer_request2)(existing_call->index,
4270 &refer_to->hvalue,
4271 &code,
4272 &call_opt);
4273 }
4274
4275 if (code < 200)
4276 code = PJSIP_SC_ACCEPTED;
4277 if (code >= 300) {
4278 /* Application rejects call transfer request */
4279 pjsip_dlg_respond( inv->dlg, rdata, code, NULL, NULL, NULL);
4280 goto on_return;
4281 }
4282
4283 PJ_LOG(3,(THIS_FILE, "Call to %.*s is being transfered to %.*s",
4284 (int)inv->dlg->remote.info_str.slen,
4285 inv->dlg->remote.info_str.ptr,
4286 (int)refer_to->hvalue.slen,
4287 refer_to->hvalue.ptr));
4288
4289 if (no_refer_sub) {
4290 /*
4291 * Always answer with 2xx.
4292 */
4293 pjsip_tx_data *tdata;
4294 const pj_str_t str_false = { "false", 5};
4295 pjsip_hdr *hdr;
4296
4297 status = pjsip_dlg_create_response(inv->dlg, rdata, code, NULL,
4298 &tdata);
4299 if (status != PJ_SUCCESS) {
4300 pjsua_perror(THIS_FILE, "Unable to create 2xx response to REFER",
4301 status);
4302 goto on_return;
4303 }
4304
4305 /* Add Refer-Sub header */
4306 hdr = (pjsip_hdr*)
4307 pjsip_generic_string_hdr_create(tdata->pool, &str_refer_sub,
4308 &str_false);
4309 pjsip_msg_add_hdr(tdata->msg, hdr);
4310
4311
4312 /* Send answer */
4313 status = pjsip_dlg_send_response(inv->dlg, pjsip_rdata_get_tsx(rdata),
4314 tdata);
4315 if (status != PJ_SUCCESS) {
4316 pjsua_perror(THIS_FILE, "Unable to create 2xx response to REFER",
4317 status);
4318 goto on_return;
4319 }
4320
4321 /* Don't have subscription */
4322 sub = NULL;
4323
4324 } else {
4325 struct pjsip_evsub_user xfer_cb;
4326 pjsip_hdr hdr_list;
4327
4328 /* Init callback */
4329 pj_bzero(&xfer_cb, sizeof(xfer_cb));
4330 xfer_cb.on_evsub_state = &xfer_server_on_evsub_state;
4331
4332 /* Init additional header list to be sent with REFER response */
4333 pj_list_init(&hdr_list);
4334
4335 /* Create transferee event subscription */
4336 status = pjsip_xfer_create_uas( inv->dlg, &xfer_cb, rdata, &sub);
4337 if (status != PJ_SUCCESS) {
4338 pjsua_perror(THIS_FILE, "Unable to create xfer uas", status);
4339 pjsip_dlg_respond( inv->dlg, rdata, 500, NULL, NULL, NULL);
4340 goto on_return;
4341 }
4342
4343 /* If there's Refer-Sub header and the value is "true", send back
4344 * Refer-Sub in the response with value "true" too.
4345 */
4346 if (refer_sub) {
4347 const pj_str_t str_true = { "true", 4 };
4348 pjsip_hdr *hdr;
4349
4350 hdr = (pjsip_hdr*)
4351 pjsip_generic_string_hdr_create(inv->dlg->pool,
4352 &str_refer_sub,
4353 &str_true);
4354 pj_list_push_back(&hdr_list, hdr);
4355
4356 }
4357
4358 /* Accept the REFER request, send 2xx. */
4359 pjsip_xfer_accept(sub, rdata, code, &hdr_list);
4360
4361 /* Create initial NOTIFY request */
4362 status = pjsip_xfer_notify( sub, PJSIP_EVSUB_STATE_ACTIVE,
4363 100, NULL, &tdata);
4364 if (status != PJ_SUCCESS) {
4365 pjsua_perror(THIS_FILE, "Unable to create NOTIFY to REFER",
4366 status);
4367 goto on_return;
4368 }
4369
4370 /* Send initial NOTIFY request */
4371 status = pjsip_xfer_send_request( sub, tdata);
4372 if (status != PJ_SUCCESS) {
4373 pjsua_perror(THIS_FILE, "Unable to send NOTIFY to REFER", status);
4374 goto on_return;
4375 }
4376 }
4377
4378 /* We're cheating here.
4379 * We need to get a null terminated string from a pj_str_t.
4380 * So grab the pointer from the hvalue and NULL terminate it, knowing
4381 * that the NULL position will be occupied by a newline.
4382 */
4383 uri = refer_to->hvalue.ptr;
4384 uri[refer_to->hvalue.slen] = '\0';
4385
4386 /* Init msg_data */
4387 pjsua_msg_data_init(&msg_data);
4388
4389 /* If Referred-By header is present in the REFER request, copy this
4390 * to the outgoing INVITE request.
4391 */
4392 if (ref_by_hdr != NULL) {
4393 pjsip_hdr *dup = (pjsip_hdr*)
4394 pjsip_hdr_clone(rdata->tp_info.pool, ref_by_hdr);
4395 pj_list_push_back(&msg_data.hdr_list, dup);
4396 }
4397
4398 /* Now make the outgoing call. */
4399 tmp = pj_str(uri);
4400 status = pjsua_call_make_call(existing_call->acc_id, &tmp, &call_opt,
4401 existing_call->user_data, &msg_data,
4402 &new_call);
4403 if (status != PJ_SUCCESS) {
4404
4405 /* Notify xferer about the error (if we have subscription) */
4406 if (sub) {
4407 status = pjsip_xfer_notify(sub, PJSIP_EVSUB_STATE_TERMINATED,
4408 500, NULL, &tdata);
4409 if (status != PJ_SUCCESS) {
4410 pjsua_perror(THIS_FILE, "Unable to create NOTIFY to REFER",
4411 status);
4412 goto on_return;
4413 }
4414 status = pjsip_xfer_send_request(sub, tdata);
4415 if (status != PJ_SUCCESS) {
4416 pjsua_perror(THIS_FILE, "Unable to send NOTIFY to REFER",
4417 status);
4418 goto on_return;
4419 }
4420 }
4421 goto on_return;
4422 }
4423
4424 if (sub) {
4425 /* Put the server subscription in inv_data.
4426 * Subsequent state changed in pjsua_inv_on_state_changed() will be
4427 * reported back to the server subscription.
4428 */
4429 pjsua_var.calls[new_call].xfer_sub = sub;
4430
4431 /* Put the invite_data in the subscription. */
4432 pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id,
4433 &pjsua_var.calls[new_call]);
4434 }
4435
4436on_return:
4437 pj_log_pop_indent();
4438}
4439
4440
4441
4442/*
4443 * This callback is called when transaction state has changed in INVITE
4444 * session. We use this to trap:
4445 * - incoming REFER request.
4446 * - incoming MESSAGE request.
4447 */
4448static void pjsua_call_on_tsx_state_changed(pjsip_inv_session *inv,
4449 pjsip_transaction *tsx,
4450 pjsip_event *e)
4451{
4452 pjsua_call *call;
4453
4454 pj_log_push_indent();
4455
4456 call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id];
4457
4458 if (call == NULL)
4459 goto on_return;
4460
4461 if (call->inv == NULL) {
4462 /* Call has been disconnected. */
4463 goto on_return;
4464 }
4465
4466 /* https://trac.pjsip.org/repos/ticket/1452:
4467 * If a request is retried due to 401/407 challenge, don't process the
4468 * transaction first but wait until we've retried it.
4469 */
4470 if (tsx->role == PJSIP_ROLE_UAC &&
4471 (tsx->status_code==401 || tsx->status_code==407) &&
4472 tsx->last_tx && tsx->last_tx->auth_retry)
4473 {
4474 goto on_return;
4475 }
4476
4477 /* Notify application callback first */
4478 if (pjsua_var.ua_cfg.cb.on_call_tsx_state) {
4479 (*pjsua_var.ua_cfg.cb.on_call_tsx_state)(call->index, tsx, e);
4480 }
4481
4482 if (tsx->role==PJSIP_ROLE_UAS &&
4483 tsx->state==PJSIP_TSX_STATE_TRYING &&
4484 pjsip_method_cmp(&tsx->method, pjsip_get_refer_method())==0)
4485 {
4486 /*
4487 * Incoming REFER request.
4488 */
4489 on_call_transfered(call->inv, e->body.tsx_state.src.rdata);
4490
4491 }
4492 else if (tsx->role==PJSIP_ROLE_UAS &&
4493 tsx->state==PJSIP_TSX_STATE_TRYING &&
4494 pjsip_method_cmp(&tsx->method, &pjsip_message_method)==0)
4495 {
4496 /*
4497 * Incoming MESSAGE request!
4498 */
4499 pjsip_rx_data *rdata;
4500 pjsip_msg *msg;
4501 pjsip_accept_hdr *accept_hdr;
4502 pj_status_t status;
4503
4504 rdata = e->body.tsx_state.src.rdata;
4505 msg = rdata->msg_info.msg;
4506
4507 /* Request MUST have message body, with Content-Type equal to
4508 * "text/plain".
4509 */
4510 if (pjsua_im_accept_pager(rdata, &accept_hdr) == PJ_FALSE) {
4511
4512 pjsip_hdr hdr_list;
4513
4514 pj_list_init(&hdr_list);
4515 pj_list_push_back(&hdr_list, accept_hdr);
4516
4517 pjsip_dlg_respond( inv->dlg, rdata, PJSIP_SC_NOT_ACCEPTABLE_HERE,
4518 NULL, &hdr_list, NULL );
4519 goto on_return;
4520 }
4521
4522 /* Respond with 200 first, so that remote doesn't retransmit in case
4523 * the UI takes too long to process the message.
4524 */
4525 status = pjsip_dlg_respond( inv->dlg, rdata, 200, NULL, NULL, NULL);
4526
4527 /* Process MESSAGE request */
4528 pjsua_im_process_pager(call->index, &inv->dlg->remote.info_str,
4529 &inv->dlg->local.info_str, rdata);
4530
4531 }
4532 else if (tsx->role == PJSIP_ROLE_UAC &&
4533 pjsip_method_cmp(&tsx->method, &pjsip_message_method)==0)
4534 {
4535 /* Handle outgoing pager status */
4536 if (tsx->status_code >= 200) {
4537 pjsua_im_data *im_data;
4538
4539 im_data = (pjsua_im_data*) tsx->mod_data[pjsua_var.mod.id];
4540 /* im_data can be NULL if this is typing indication */
4541
4542 if (im_data && pjsua_var.ua_cfg.cb.on_pager_status) {
4543 pjsua_var.ua_cfg.cb.on_pager_status(im_data->call_id,
4544 &im_data->to,
4545 &im_data->body,
4546 im_data->user_data,
4547 (pjsip_status_code)
4548 tsx->status_code,
4549 &tsx->status_text);
4550 }
4551 }
4552 } else if (tsx->role == PJSIP_ROLE_UAC &&
4553 tsx->last_tx == (pjsip_tx_data*)call->hold_msg &&
4554 tsx->state >= PJSIP_TSX_STATE_COMPLETED)
4555 {
4556 /* Monitor the status of call hold request */
4557 call->hold_msg = NULL;
4558 if (tsx->status_code/100 != 2) {
4559 /* Outgoing call hold failed */
4560 call->local_hold = PJ_FALSE;
4561 PJ_LOG(3,(THIS_FILE, "Error putting call %d on hold (reason=%d)",
4562 call->index, tsx->status_code));
4563 }
4564 } else if (tsx->role == PJSIP_ROLE_UAC &&
4565 (call->opt.flag & PJSUA_CALL_UNHOLD) &&
4566 tsx->state >= PJSIP_TSX_STATE_COMPLETED)
4567 {
4568 /* Monitor the status of call unhold request */
4569 if (tsx->status_code/100 != 2 &&
4570 (tsx->status_code!=401 && tsx->status_code!=407))
4571 {
4572 /* Call unhold failed */
4573 call->opt.flag &= ~PJSUA_CALL_UNHOLD;
4574 call->local_hold = PJ_TRUE;
4575 PJ_LOG(3,(THIS_FILE, "Error releasing hold on call %d (reason=%d)",
4576 call->index, tsx->status_code));
4577 }
4578 } else if (tsx->role==PJSIP_ROLE_UAS &&
4579 tsx->state==PJSIP_TSX_STATE_TRYING &&
4580 pjsip_method_cmp(&tsx->method, &pjsip_info_method)==0)
4581 {
4582 /*
4583 * Incoming INFO request for media control.
4584 */
4585 const pj_str_t STR_APPLICATION = { "application", 11};
4586 const pj_str_t STR_MEDIA_CONTROL_XML = { "media_control+xml", 17 };
4587 pjsip_rx_data *rdata = e->body.tsx_state.src.rdata;
4588 pjsip_msg_body *body = rdata->msg_info.msg->body;
4589
4590 if (body && body->len &&
4591 pj_stricmp(&body->content_type.type, &STR_APPLICATION)==0 &&
4592 pj_stricmp(&body->content_type.subtype, &STR_MEDIA_CONTROL_XML)==0)
4593 {
4594 pjsip_tx_data *tdata;
4595 pj_str_t control_st;
4596 pj_status_t status;
4597
4598 /* Apply and answer the INFO request */
4599 pj_strset(&control_st, (char*)body->data, body->len);
4600 status = pjsua_media_apply_xml_control(call->index, &control_st);
4601 if (status == PJ_SUCCESS) {
4602 status = pjsip_endpt_create_response(tsx->endpt, rdata,
4603 200, NULL, &tdata);
4604 if (status == PJ_SUCCESS)
4605 status = pjsip_tsx_send_msg(tsx, tdata);
4606 } else {
4607 status = pjsip_endpt_create_response(tsx->endpt, rdata,
4608 400, NULL, &tdata);
4609 if (status == PJ_SUCCESS)
4610 status = pjsip_tsx_send_msg(tsx, tdata);
4611 }
4612 }
4613 }
4614
4615on_return:
4616 pj_log_pop_indent();
4617}
4618
4619
4620/* Redirection handler */
4621static pjsip_redirect_op pjsua_call_on_redirected(pjsip_inv_session *inv,
4622 const pjsip_uri *target,
4623 const pjsip_event *e)
4624{
4625 pjsua_call *call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id];
4626 pjsip_redirect_op op;
4627
4628 pj_log_push_indent();
4629
4630 if (pjsua_var.ua_cfg.cb.on_call_redirected) {
4631 op = (*pjsua_var.ua_cfg.cb.on_call_redirected)(call->index,
4632 target, e);
4633 } else {
4634 PJ_LOG(4,(THIS_FILE, "Unhandled redirection for call %d "
4635 "(callback not implemented by application). Disconnecting "
4636 "call.",
4637 call->index));
4638 op = PJSIP_REDIRECT_STOP;
4639 }
4640
4641 pj_log_pop_indent();
4642
4643 return op;
4644}
4645