1
/* $Id: pjsua_call.c 4411 2013-03-04 04:34:38Z nanang $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
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.
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.
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
20
#include <pjsua-lib/pjsua.h>
21
#include <pjsua-lib/pjsua_internal.h>
24
#define THIS_FILE "pjsua_call.c"
27
/* Retry interval of sending re-INVITE for locking a codec when remote
28
* SDP answer contains multiple codec, in milliseconds.
30
#define LOCK_CODEC_RETRY_INTERVAL 200
33
* Max UPDATE/re-INVITE retry to lock codec
35
#define LOCK_CODEC_MAX_RETRY 5
41
const pjsip_method pjsip_info_method =
48
/* This callback receives notification from invite session when the
49
* session state has changed.
51
static void pjsua_call_on_state_changed(pjsip_inv_session *inv,
54
/* This callback is called by invite session framework when UAC session
57
static void pjsua_call_on_forked( pjsip_inv_session *inv,
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
65
static void pjsua_call_on_media_update(pjsip_inv_session *inv,
69
* Called when session received new offer.
71
static void pjsua_call_on_rx_offer(pjsip_inv_session *inv,
72
const pjmedia_sdp_session *offer);
75
* Called to generate new offer.
77
static void pjsua_call_on_create_offer(pjsip_inv_session *inv,
78
pjmedia_sdp_session **offer);
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.
86
static void pjsua_call_on_tsx_state_changed(pjsip_inv_session *inv,
87
pjsip_transaction *tsx,
91
* Redirection handler.
93
static pjsip_redirect_op pjsua_call_on_redirected(pjsip_inv_session *inv,
94
const pjsip_uri *target,
95
const pjsip_event *e);
98
/* Create SDP for call hold. */
99
static pj_status_t create_sdp_of_call_hold(pjsua_call *call,
100
pjmedia_sdp_session **p_sdp);
103
* Callback called by event framework when the xfer subscription state
106
static void xfer_client_on_evsub_state( pjsip_evsub *sub, pjsip_event *event);
107
static void xfer_server_on_evsub_state( pjsip_evsub *sub, pjsip_event *event);
109
/* Timer callback to send re-INVITE/UPDATE to lock codec or ICE update */
110
static void reinv_timer_cb(pj_timer_heap_t *th, pj_timer_entry *entry);
112
/* Check and send reinvite for lock codec and ICE update */
113
static pj_status_t process_pending_reinvite(pjsua_call *call);
116
* Reset call descriptor.
118
static void reset_call(pjsua_call_id id)
120
pjsua_call *call = &pjsua_var.calls[id];
123
pj_bzero(call, sizeof(*call));
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;
134
call_med->tp_auto_del = PJ_TRUE;
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);
143
* Init call subsystem.
145
pj_status_t pjsua_call_subsys_init(const pjsua_config *cfg)
147
pjsip_inv_callback inv_cb;
149
const pj_str_t str_norefersub = { "norefersub", 10 };
152
/* Init calls array. */
153
for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.calls); ++i)
157
pjsua_config_dup(pjsua_var.pool, &pjsua_var.ua_cfg, cfg);
159
/* Verify settings */
160
if (pjsua_var.ua_cfg.max_calls >= PJSUA_MAX_CALLS) {
161
pjsua_var.ua_cfg.max_calls = PJSUA_MAX_CALLS;
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)
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;
182
/* Initialize invite session module: */
183
status = pjsip_inv_usage_init(pjsua_var.endpt, &inv_cb);
184
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
186
/* Add "norefersub" in Supported header */
187
pjsip_endpt_add_capability(pjsua_var.endpt, NULL, PJSIP_H_SUPPORTED,
188
NULL, 1, &str_norefersub);
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);
199
* Start call subsystem.
201
pj_status_t pjsua_call_subsys_start(void)
209
* Get maximum number of calls configured in pjsua.
211
PJ_DEF(unsigned) pjsua_call_get_max_count(void)
213
return pjsua_var.ua_cfg.max_calls;
218
* Get number of currently active calls.
220
PJ_DEF(unsigned) pjsua_call_get_count(void)
222
return pjsua_var.call_cnt;
229
PJ_DEF(pj_status_t) pjsua_enum_calls( pjsua_call_id ids[],
234
PJ_ASSERT_RETURN(ids && *count, PJ_EINVAL);
238
for (i=0, c=0; c<*count && i<pjsua_var.ua_cfg.max_calls; ++i) {
239
if (!pjsua_var.calls[i].inv)
253
/* Allocate one call id */
254
static pjsua_call_id alloc_call_id(void)
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)
263
pjsua_var.next_call_id = 0;
266
for (cid=pjsua_var.next_call_id;
267
cid<(int)pjsua_var.ua_cfg.max_calls;
270
if (pjsua_var.calls[cid].inv == NULL &&
271
pjsua_var.calls[cid].async_call.dlg == NULL)
273
++pjsua_var.next_call_id;
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)
282
++pjsua_var.next_call_id;
289
for (cid=0; cid<(int)pjsua_var.ua_cfg.max_calls; ++cid) {
290
if (pjsua_var.calls[cid].inv == NULL)
295
return PJSUA_INVALID_ID;
298
/* Get signaling secure level.
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.
304
static int get_secure_level(pjsua_acc_id acc_id, const pj_str_t *dst_uri)
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];
310
if (pj_stristr(dst_uri, &sips))
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;
318
sip_uri = (pjsip_sip_uri*)pjsip_uri_get_uri(uri);
319
if (pj_stricmp2(&sip_uri->transport_param, "tls")==0)
323
if (pj_stristr(dst_uri, &tls))
331
static int call_get_secure_level(pjsua_call *call)
333
if (call->inv->dlg->secure)
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;
341
sip_uri = (pjsip_sip_uri*)pjsip_uri_get_uri(uri);
342
if (pj_stricmp2(&sip_uri->transport_param, "tls")==0)
346
pjsip_sip_uri *sip_uri;
348
if (PJSIP_URI_SCHEME_IS_SIPS(call->inv->dlg->target))
350
if (!PJSIP_URI_SCHEME_IS_SIP(call->inv->dlg->target))
353
sip_uri = (pjsip_sip_uri*) pjsip_uri_get_uri(call->inv->dlg->target);
354
if (pj_stricmp2(&sip_uri->transport_param, "tls")==0)
362
/* Outgoing call callback when media transport creation is completed. */
364
on_make_call_med_tp_complete(pjsua_call_id call_id,
365
const pjsua_med_tp_state_info *info)
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);
379
/* Increment the dialog's lock otherwise when invite session creation
380
* fails the dialog will be destroyed prematurely.
382
pjsip_dlg_inc_lock(dlg);
384
/* Decrement dialog session. */
385
pjsip_dlg_dec_session(dlg, &pjsua_var.mod);
387
if (status != PJ_SUCCESS) {
391
call->last_code = PJSIP_SC_TEMPORARILY_UNAVAILABLE;
392
pj_strcpy2(&call->last_text, "Media init error: ");
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;
399
pjsua_perror(THIS_FILE, "Error initializing media channel", status);
403
/* pjsua_media_channel_deinit() has been called or
404
* call has been hung up.
406
if (call->async_call.med_ch_deinit ||
407
call->async_call.call_var.out_call.hangup)
409
PJ_LOG(4,(THIS_FILE, "Call has been hung up or media channel has "
410
"been deinitialized"));
415
status = pjsua_media_channel_create_sdp(call->index, dlg->pool, NULL,
417
if (status != PJ_SUCCESS) {
418
pjsua_perror(THIS_FILE, "Error initializing media channel", status);
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;
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);
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);
447
/* Create and associate our data in the session. */
450
dlg->mod_data[pjsua_var.mod.id] = call;
451
inv->mod_data[pjsua_var.mod.id] = call;
453
/* If account is locked to specific transport, then lock dialog
454
* to this transport too.
456
if (acc->cfg.transport_id != PJSUA_INVALID_ID) {
457
pjsip_tpselector tp_sel;
459
pjsua_init_tpselector(acc->cfg.transport_id, &tp_sel);
460
pjsip_dlg_set_transport(dlg, &tp_sel);
463
/* Set dialog Route-Set: */
464
if (!pj_list_empty(&acc->route_set))
465
pjsip_dlg_set_route_set(dlg, &acc->route_set);
468
/* Set credentials: */
470
pjsip_auth_clt_set_credentials( &dlg->auth_sess,
471
acc->cred_cnt, acc->cred);
474
/* Set authentication preference */
475
pjsip_auth_clt_set_prefs(&dlg->auth_sess, &acc->cfg.auth_pref);
477
/* Create initial INVITE: */
479
status = pjsip_inv_invite(inv, &tdata);
480
if (status != PJ_SUCCESS) {
481
pjsua_perror(THIS_FILE, "Unable to create initial INVITE request",
487
/* Add additional headers etc */
489
pjsua_process_msg_data( tdata,
490
call->async_call.call_var.out_call.msg_data);
492
/* Must increment call counter now */
493
++pjsua_var.call_cnt;
495
/* Send initial INVITE: */
497
status = pjsip_inv_send_msg(inv, tdata);
498
if (status != PJ_SUCCESS) {
501
/* Upon failure to send first request, the invite
502
* session would have been cleared.
509
call->med_ch_cb = NULL;
511
pjsip_dlg_dec_lock(dlg);
517
if (inv == NULL && call_id != -1 && !cb_called &&
518
pjsua_var.ua_cfg.cb.on_call_state)
520
(*pjsua_var.ua_cfg.cb.on_call_state)(call_id, NULL);
524
/* This may destroy the dialog */
525
pjsip_dlg_dec_lock(dlg);
529
pjsip_inv_terminate(inv, PJSIP_SC_OK, PJ_FALSE);
534
pjsua_media_channel_deinit(call_id);
537
call->med_ch_cb = NULL;
539
pjsua_check_snd_dev_idle();
547
* Initialize call settings based on account ID.
549
PJ_DEF(void) pjsua_call_setting_default(pjsua_call_setting *opt)
553
pj_bzero(opt, sizeof(*opt));
554
opt->flag = PJSUA_CALL_INCLUDE_DISABLED_MEDIA;
557
#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
559
opt->req_keyframe_method = PJSUA_VID_REQ_KEYFRAME_SIP_INFO |
560
PJSUA_VID_REQ_KEYFRAME_RTCP_PLI;
564
static pj_status_t apply_call_setting(pjsua_call *call,
565
const pjsua_call_setting *opt,
566
const pjmedia_sdp_session *rem_sdp)
573
#if !PJMEDIA_HAS_VIDEO
574
pj_assert(opt->vid_cnt == 0);
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;
584
status = pjsua_media_channel_init(call->index, role,
586
call->inv->pool_prov,
589
if (status != PJ_SUCCESS) {
590
pjsua_perror(THIS_FILE, "Error re-initializing media channel",
600
* Make outgoing call to the specified URI using the specified account.
602
PJ_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,
606
const pjsua_msg_data *msg_data,
607
pjsua_call_id *p_call_id)
609
pj_pool_t *tmp_pool = NULL;
610
pjsip_dialog *dlg = NULL;
618
/* Check that account is valid */
619
PJ_ASSERT_RETURN(acc_id>=0 || acc_id<(int)PJ_ARRAY_SIZE(pjsua_var.acc),
622
/* Check arguments */
623
PJ_ASSERT_RETURN(dest_uri, PJ_EINVAL);
625
PJ_LOG(4,(THIS_FILE, "Making call with acc #%d to %.*s", acc_id,
626
(int)dest_uri->slen, dest_uri->ptr));
628
pj_log_push_indent();
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
637
if (!pjsua_var.is_mswitch && pjsua_var.snd_port==NULL &&
638
pjsua_var.null_snd==NULL && !pjsua_var.no_snd)
640
status = pjsua_set_snd_dev(pjsua_var.cap_dev, pjsua_var.play_dev);
641
if (status != PJ_SUCCESS)
645
acc = &pjsua_var.acc[acc_id];
647
pjsua_perror(THIS_FILE, "Unable to make call because account "
648
"is not valid", PJ_EINVALIDOP);
649
status = PJ_EINVALIDOP;
653
/* Find free call slot. */
654
call_id = alloc_call_id();
656
if (call_id == PJSUA_INVALID_ID) {
657
pjsua_perror(THIS_FILE, "Error making call", PJ_ETOOMANY);
658
status = PJ_ETOOMANY;
662
call = &pjsua_var.calls[call_id];
664
/* Associate session with account */
665
call->acc_id = acc_id;
666
call->call_hold_type = acc->cfg.call_hold_type;
668
/* Apply call setting */
669
status = apply_call_setting(call, opt, NULL);
670
if (status != PJ_SUCCESS) {
671
pjsua_perror(THIS_FILE, "Failed to apply call setting", status);
675
/* Create temporary pool */
676
tmp_pool = pjsua_pool_create("tmpcall10", 512, 256);
678
/* Verify that destination URI is valid before calling
679
* pjsua_acc_create_uac_contact, or otherwise there
680
* a misleading "Invalid Contact URI" error will be printed
681
* when pjsua_acc_create_uac_contact() fails.
687
pj_strdup_with_null(tmp_pool, &dup, dest_uri);
688
uri = pjsip_parse_uri(tmp_pool, dup.ptr, dup.slen, 0);
691
pjsua_perror(THIS_FILE, "Unable to make call",
692
PJSIP_EINVALIDREQURI);
693
status = PJSIP_EINVALIDREQURI;
698
/* Mark call start time. */
699
pj_gettimeofday(&call->start_time);
701
/* Reset first response time */
702
call->res_time.sec = 0;
704
/* Create suitable Contact header unless a Contact header has been
705
* set in the account.
707
if (acc->contact.slen) {
708
contact = acc->contact;
710
status = pjsua_acc_create_uac_contact(tmp_pool, &contact,
712
if (status != PJ_SUCCESS) {
713
pjsua_perror(THIS_FILE, "Unable to generate Contact header",
719
/* Create outgoing dialog: */
720
status = pjsip_dlg_create_uac( pjsip_ua_instance(),
721
&acc->cfg.id, &contact,
722
dest_uri, dest_uri, &dlg);
723
if (status != PJ_SUCCESS) {
724
pjsua_perror(THIS_FILE, "Dialog creation failed", status);
728
/* Increment the dialog's lock otherwise when invite session creation
729
* fails the dialog will be destroyed prematurely.
731
pjsip_dlg_inc_lock(dlg);
733
if (acc->cfg.allow_via_rewrite && acc->via_addr.host.slen > 0)
734
pjsip_dlg_set_via_sent_by(dlg, &acc->via_addr, acc->via_tp);
736
/* Calculate call's secure level */
737
call->secure_level = get_secure_level(acc_id, dest_uri);
739
/* Attach user data */
740
call->user_data = user_data;
742
/* Store variables required for the callback after the async
743
* media transport creation is completed.
746
call->async_call.call_var.out_call.msg_data = pjsua_msg_data_clone(
747
dlg->pool, msg_data);
749
call->async_call.dlg = dlg;
751
/* Temporarily increment dialog session. Without this, dialog will be
752
* prematurely destroyed if dec_lock() is called on the dialog before
753
* the invite session is created.
755
pjsip_dlg_inc_session(dlg, &pjsua_var.mod);
757
/* Init media channel */
758
status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAC,
759
call->secure_level, dlg->pool,
761
&on_make_call_med_tp_complete);
762
if (status == PJ_SUCCESS) {
763
status = on_make_call_med_tp_complete(call->index, NULL);
764
if (status != PJ_SUCCESS)
766
} else if (status != PJ_EPENDING) {
767
pjsua_perror(THIS_FILE, "Error initializing media channel", status);
768
pjsip_dlg_dec_session(dlg, &pjsua_var.mod);
775
*p_call_id = call_id;
777
pjsip_dlg_dec_lock(dlg);
778
pj_pool_release(tmp_pool);
788
/* This may destroy the dialog */
789
pjsip_dlg_dec_lock(dlg);
794
pjsua_media_channel_deinit(call_id);
798
pj_pool_release(tmp_pool);
806
/* Get the NAT type information in remote's SDP */
807
static void update_remote_nat_type(pjsua_call *call,
808
const pjmedia_sdp_session *sdp)
810
const pjmedia_sdp_attr *xnat;
812
xnat = pjmedia_sdp_attr_find2(sdp->attr_count, sdp->attr, "X-nat", NULL);
814
call->rem_nat_type = (pj_stun_nat_type) (xnat->value.ptr[0] - '0');
816
call->rem_nat_type = PJ_STUN_NAT_TYPE_UNKNOWN;
819
PJ_LOG(5,(THIS_FILE, "Call %d: remote NAT type is %d (%s)", call->index,
820
call->rem_nat_type, pj_stun_get_nat_name(call->rem_nat_type)));
824
static pj_status_t process_incoming_call_replace(pjsua_call *call,
825
pjsip_dialog *replaced_dlg)
827
pjsip_inv_session *replaced_inv;
828
struct pjsua_call *replaced_call;
829
pjsip_tx_data *tdata = NULL;
830
pj_status_t status = PJ_SUCCESS;
832
/* Get the invite session in the dialog */
833
replaced_inv = pjsip_dlg_get_inv_session(replaced_dlg);
835
/* Get the replaced call instance */
836
replaced_call = (pjsua_call*) replaced_dlg->mod_data[pjsua_var.mod.id];
838
/* Notify application */
839
if (pjsua_var.ua_cfg.cb.on_call_replaced)
840
pjsua_var.ua_cfg.cb.on_call_replaced(replaced_call->index,
843
if (replaced_call->inv->state <= PJSIP_INV_STATE_EARLY &&
844
replaced_call->inv->role != PJSIP_ROLE_UAC)
846
if (replaced_call->last_code > 100 && replaced_call->last_code < 200)
848
pjsip_status_code code = replaced_call->last_code;
849
pj_str_t *text = &replaced_call->last_text;
851
PJ_LOG(4,(THIS_FILE, "Answering replacement call %d with %d/%.*s",
852
call->index, code, text->slen, text->ptr));
854
/* Answer the new call with last response in the replaced call */
855
status = pjsip_inv_answer(call->inv, code, text, NULL, &tdata);
858
PJ_LOG(4,(THIS_FILE, "Answering replacement call %d with 200/OK",
861
/* Answer the new call with 200 response */
862
status = pjsip_inv_answer(call->inv, 200, NULL, NULL, &tdata);
865
if (status == PJ_SUCCESS && tdata)
866
status = pjsip_inv_send_msg(call->inv, tdata);
868
if (status != PJ_SUCCESS)
869
pjsua_perror(THIS_FILE, "Error answering session", status);
871
/* Note that inv may be invalid if 200/OK has caused error in
872
* starting the media.
875
PJ_LOG(4,(THIS_FILE, "Disconnecting replaced call %d",
876
replaced_call->index));
878
/* Disconnect replaced invite session */
879
status = pjsip_inv_end_session(replaced_inv, PJSIP_SC_GONE, NULL,
881
if (status == PJ_SUCCESS && tdata)
882
status = pjsip_inv_send_msg(replaced_inv, tdata);
884
if (status != PJ_SUCCESS)
885
pjsua_perror(THIS_FILE, "Error terminating session", status);
891
static void process_pending_call_answer(pjsua_call *call)
893
struct call_answer *answer, *next;
895
answer = call->async_call.call_var.inc_call.answers.next;
896
while (answer != &call->async_call.call_var.inc_call.answers) {
898
pjsua_call_answer2(call->index, answer->opt, answer->code,
899
answer->reason, answer->msg_data);
901
/* Call might have been disconnected if application is answering
902
* with 200/OK and the media failed to start.
903
* See pjsua_call_answer() below.
905
if (!call->inv || !call->inv->pool_prov)
908
pj_list_erase(answer);
914
/* Incoming call callback when media transport creation is completed. */
916
on_incoming_call_med_tp_complete(pjsua_call_id call_id,
917
const pjsua_med_tp_state_info *info)
919
pjsua_call *call = &pjsua_var.calls[call_id];
920
const pjmedia_sdp_session *offer=NULL;
921
pjmedia_sdp_session *answer;
922
pjsip_tx_data *response = NULL;
923
unsigned options = 0;
924
int sip_err_code = (info? info->sip_err_code: 0);
925
pj_status_t status = (info? info->status: PJ_SUCCESS);
929
if (status != PJ_SUCCESS) {
930
pjsua_perror(THIS_FILE, "Error initializing media channel", status);
934
/* pjsua_media_channel_deinit() has been called. */
935
if (call->async_call.med_ch_deinit) {
936
pjsua_media_channel_deinit(call->index);
937
call->med_ch_cb = NULL;
942
/* Get remote SDP offer (if any). */
944
pjmedia_sdp_neg_get_neg_remote(call->inv->neg, &offer);
946
status = pjsua_media_channel_create_sdp(call_id,
947
call->async_call.dlg->pool,
948
offer, &answer, &sip_err_code);
949
if (status != PJ_SUCCESS) {
950
pjsua_perror(THIS_FILE, "Error creating SDP answer", status);
954
status = pjsip_inv_set_local_sdp(call->inv, answer);
955
if (status != PJ_SUCCESS) {
956
pjsua_perror(THIS_FILE, "Error setting local SDP", status);
957
sip_err_code = PJSIP_SC_NOT_ACCEPTABLE_HERE;
961
/* Verify that we can handle the request. */
962
status = pjsip_inv_verify_request3(NULL,
963
call->inv->pool_prov, &options, offer,
964
answer, NULL, pjsua_var.endpt, &response);
965
if (status != PJ_SUCCESS) {
967
* No we can't handle the incoming INVITE request.
969
sip_err_code = PJSIP_ERRNO_TO_SIP_STATUS(status);
974
if (status != PJ_SUCCESS) {
975
/* If the callback is called from pjsua_call_on_incoming(), the
976
* invite's state is PJSIP_INV_STATE_NULL, so the invite session
977
* will be terminated later, otherwise we end the session here.
979
if (call->inv->state > PJSIP_INV_STATE_NULL) {
980
pjsip_tx_data *tdata;
983
status_ = pjsip_inv_end_session(call->inv, sip_err_code, NULL,
985
if (status_ == PJ_SUCCESS && tdata)
986
status_ = pjsip_inv_send_msg(call->inv, tdata);
989
pjsua_media_channel_deinit(call->index);
992
/* Set the callback to NULL to indicate that the async operation
995
call->med_ch_cb = NULL;
997
/* Finish any pending process */
998
if (status == PJ_SUCCESS) {
999
if (call->async_call.call_var.inc_call.replaced_dlg) {
1000
/* Process pending call replace */
1001
pjsip_dialog *replaced_dlg =
1002
call->async_call.call_var.inc_call.replaced_dlg;
1003
process_incoming_call_replace(call, replaced_dlg);
1005
/* Process pending call answers */
1006
process_pending_call_answer(call);
1016
* Handle incoming INVITE request.
1017
* Called by pjsua_core.c
1019
pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
1022
pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata);
1023
pjsip_dialog *replaced_dlg = NULL;
1024
pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
1025
pjsip_msg *msg = rdata->msg_info.msg;
1026
pjsip_tx_data *response = NULL;
1027
unsigned options = 0;
1028
pjsip_inv_session *inv = NULL;
1032
int sip_err_code = PJSIP_SC_INTERNAL_SERVER_ERROR;
1033
pjmedia_sdp_session *offer=NULL;
1036
/* Don't want to handle anything but INVITE */
1037
if (msg->line.req.method.id != PJSIP_INVITE_METHOD)
1040
/* Don't want to handle anything that's already associated with
1041
* existing dialog or transaction.
1046
/* Don't want to accept the call if shutdown is in progress */
1047
if (pjsua_var.thread_quit_flag) {
1048
pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata,
1049
PJSIP_SC_TEMPORARILY_UNAVAILABLE, NULL,
1054
PJ_LOG(4,(THIS_FILE, "Incoming %s", rdata->msg_info.info));
1055
pj_log_push_indent();
1059
/* Find free call slot. */
1060
call_id = alloc_call_id();
1062
if (call_id == PJSUA_INVALID_ID) {
1063
pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata,
1064
PJSIP_SC_BUSY_HERE, NULL,
1066
PJ_LOG(2,(THIS_FILE,
1067
"Unable to accept incoming call (too many calls)"));
1071
/* Clear call descriptor */
1072
reset_call(call_id);
1074
call = &pjsua_var.calls[call_id];
1076
/* Mark call start time. */
1077
pj_gettimeofday(&call->start_time);
1079
/* Check INVITE request for Replaces header. If Replaces header is
1080
* present, the function will make sure that we can handle the request.
1082
status = pjsip_replaces_verify_request(rdata, &replaced_dlg, PJ_FALSE,
1084
if (status != PJ_SUCCESS) {
1086
* Something wrong with the Replaces header.
1089
pjsip_response_addr res_addr;
1091
pjsip_get_response_addr(response->pool, rdata, &res_addr);
1092
pjsip_endpt_send_response(pjsua_var.endpt, &res_addr, response,
1097
/* Respond with 500 (Internal Server Error) */
1098
pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 500, NULL,
1105
/* If this INVITE request contains Replaces header, notify application
1106
* about the request so that application can do subsequent checking
1109
if (replaced_dlg != NULL &&
1110
(pjsua_var.ua_cfg.cb.on_call_replace_request ||
1111
pjsua_var.ua_cfg.cb.on_call_replace_request2))
1113
pjsua_call *replaced_call;
1115
pj_str_t st_text = { "OK", 2 };
1117
/* Get the replaced call instance */
1118
replaced_call = (pjsua_call*) replaced_dlg->mod_data[pjsua_var.mod.id];
1120
/* Copy call setting from the replaced call */
1121
call->opt = replaced_call->opt;
1123
/* Notify application */
1124
if (pjsua_var.ua_cfg.cb.on_call_replace_request) {
1125
pjsua_var.ua_cfg.cb.on_call_replace_request(replaced_call->index,
1127
&st_code, &st_text);
1130
if (pjsua_var.ua_cfg.cb.on_call_replace_request2) {
1131
pjsua_var.ua_cfg.cb.on_call_replace_request2(replaced_call->index,
1137
/* Must specify final response */
1138
PJ_ASSERT_ON_FAIL(st_code >= 200, st_code = 200);
1140
/* Check if application rejects this request. */
1141
if (st_code >= 300) {
1143
if (st_text.slen == 2)
1144
st_text = *pjsip_get_status_text(st_code);
1146
pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata,
1147
st_code, &st_text, NULL, NULL, NULL);
1153
* Get which account is most likely to be associated with this incoming
1154
* call. We need the account to find which contact URI to put for
1157
acc_id = call->acc_id = pjsua_acc_find_for_incoming(rdata);
1158
call->call_hold_type = pjsua_var.acc[acc_id].cfg.call_hold_type;
1160
/* Get call's secure level */
1161
if (PJSIP_URI_SCHEME_IS_SIPS(rdata->msg_info.msg->line.req.uri))
1162
call->secure_level = 2;
1163
else if (PJSIP_TRANSPORT_IS_SECURE(rdata->tp_info.transport))
1164
call->secure_level = 1;
1166
call->secure_level = 0;
1168
/* Parse SDP from incoming request */
1169
if (rdata->msg_info.msg->body) {
1170
pjsip_rdata_sdp_info *sdp_info;
1172
sdp_info = pjsip_rdata_get_sdp_info(rdata);
1173
offer = sdp_info->sdp;
1175
status = sdp_info->sdp_err;
1176
if (status==PJ_SUCCESS && sdp_info->sdp==NULL)
1177
status = PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_NOT_ACCEPTABLE);
1179
if (status != PJ_SUCCESS) {
1180
const pj_str_t reason = pj_str("Bad SDP");
1182
pjsip_warning_hdr *w;
1184
pjsua_perror(THIS_FILE, "Bad SDP in incoming INVITE",
1187
w = pjsip_warning_hdr_create_from_status(rdata->tp_info.pool,
1188
pjsip_endpt_name(pjsua_var.endpt),
1190
pj_list_init(&hdr_list);
1191
pj_list_push_back(&hdr_list, w);
1193
pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata, 400,
1194
&reason, &hdr_list, NULL, NULL);
1198
/* Do quick checks on SDP before passing it to transports. More elabore
1199
* checks will be done in pjsip_inv_verify_request2() below.
1201
if (offer->media_count==0) {
1202
const pj_str_t reason = pj_str("Missing media in SDP");
1203
pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata, 400, &reason,
1212
/* Verify that we can handle the request. */
1213
options |= PJSIP_INV_SUPPORT_100REL;
1214
options |= PJSIP_INV_SUPPORT_TIMER;
1215
if (pjsua_var.acc[acc_id].cfg.require_100rel == PJSUA_100REL_MANDATORY)
1216
options |= PJSIP_INV_REQUIRE_100REL;
1217
if (pjsua_var.acc[acc_id].cfg.ice_cfg.enable_ice)
1218
options |= PJSIP_INV_SUPPORT_ICE;
1219
if (pjsua_var.acc[acc_id].cfg.use_timer == PJSUA_SIP_TIMER_REQUIRED)
1220
options |= PJSIP_INV_REQUIRE_TIMER;
1221
else if (pjsua_var.acc[acc_id].cfg.use_timer == PJSUA_SIP_TIMER_ALWAYS)
1222
options |= PJSIP_INV_ALWAYS_USE_TIMER;
1224
status = pjsip_inv_verify_request2(rdata, &options, offer, NULL, NULL,
1225
pjsua_var.endpt, &response);
1226
if (status != PJ_SUCCESS) {
1229
* No we can't handle the incoming INVITE request.
1232
pjsip_response_addr res_addr;
1234
pjsip_get_response_addr(response->pool, rdata, &res_addr);
1235
pjsip_endpt_send_response(pjsua_var.endpt, &res_addr, response,
1239
/* Respond with 500 (Internal Server Error) */
1240
pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata, 500, NULL,
1247
/* Get suitable Contact header */
1248
if (pjsua_var.acc[acc_id].contact.slen) {
1249
contact = pjsua_var.acc[acc_id].contact;
1251
status = pjsua_acc_create_uas_contact(rdata->tp_info.pool, &contact,
1253
if (status != PJ_SUCCESS) {
1254
pjsua_perror(THIS_FILE, "Unable to generate Contact header",
1256
pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 500, NULL,
1262
/* Create dialog: */
1263
status = pjsip_dlg_create_uas( pjsip_ua_instance(), rdata,
1265
if (status != PJ_SUCCESS) {
1266
pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 500, NULL,
1271
if (pjsua_var.acc[acc_id].cfg.allow_via_rewrite &&
1272
pjsua_var.acc[acc_id].via_addr.host.slen > 0)
1274
pjsip_dlg_set_via_sent_by(dlg, &pjsua_var.acc[acc_id].via_addr,
1275
pjsua_var.acc[acc_id].via_tp);
1278
/* Set credentials */
1279
if (pjsua_var.acc[acc_id].cred_cnt) {
1280
pjsip_auth_clt_set_credentials(&dlg->auth_sess,
1281
pjsua_var.acc[acc_id].cred_cnt,
1282
pjsua_var.acc[acc_id].cred);
1285
/* Set preference */
1286
pjsip_auth_clt_set_prefs(&dlg->auth_sess,
1287
&pjsua_var.acc[acc_id].cfg.auth_pref);
1289
/* Disable Session Timers if not prefered and the incoming INVITE request
1290
* did not require it.
1292
if (pjsua_var.acc[acc_id].cfg.use_timer == PJSUA_SIP_TIMER_INACTIVE &&
1293
(options & PJSIP_INV_REQUIRE_TIMER) == 0)
1295
options &= ~(PJSIP_INV_SUPPORT_TIMER);
1298
/* If 100rel is optional and UAC supports it, use it. */
1299
if ((options & PJSIP_INV_REQUIRE_100REL)==0 &&
1300
pjsua_var.acc[acc_id].cfg.require_100rel == PJSUA_100REL_OPTIONAL)
1302
const pj_str_t token = { "100rel", 6};
1303
pjsip_dialog_cap_status cap_status;
1305
cap_status = pjsip_dlg_remote_has_cap(dlg, PJSIP_H_SUPPORTED, NULL,
1307
if (cap_status == PJSIP_DIALOG_CAP_SUPPORTED)
1308
options |= PJSIP_INV_REQUIRE_100REL;
1311
/* Create invite session: */
1312
status = pjsip_inv_create_uas( dlg, rdata, NULL, options, &inv);
1313
if (status != PJ_SUCCESS) {
1315
pjsip_warning_hdr *w;
1317
w = pjsip_warning_hdr_create_from_status(dlg->pool,
1318
pjsip_endpt_name(pjsua_var.endpt),
1320
pj_list_init(&hdr_list);
1321
pj_list_push_back(&hdr_list, w);
1323
pjsip_dlg_respond(dlg, rdata, 500, NULL, &hdr_list, NULL);
1325
/* Can't terminate dialog because transaction is in progress.
1326
pjsip_dlg_terminate(dlg);
1331
/* If account is locked to specific transport, then lock dialog
1332
* to this transport too.
1334
if (pjsua_var.acc[acc_id].cfg.transport_id != PJSUA_INVALID_ID) {
1335
pjsip_tpselector tp_sel;
1337
pjsua_init_tpselector(pjsua_var.acc[acc_id].cfg.transport_id, &tp_sel);
1338
pjsip_dlg_set_transport(dlg, &tp_sel);
1341
/* Create and attach pjsua_var data to the dialog */
1344
/* Store variables required for the callback after the async
1345
* media transport creation is completed.
1347
call->async_call.dlg = dlg;
1348
pj_list_init(&call->async_call.call_var.inc_call.answers);
1350
/* Init media channel, only when there is offer or call replace request.
1351
* For incoming call without SDP offer, media channel init will be done
1352
* in pjsua_call_answer(), see ticket #1526.
1354
if (offer || replaced_dlg) {
1355
status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAS,
1357
rdata->tp_info.pool,
1359
&sip_err_code, PJ_TRUE,
1360
&on_incoming_call_med_tp_complete);
1361
if (status == PJ_SUCCESS) {
1362
status = on_incoming_call_med_tp_complete(call_id, NULL);
1363
if (status != PJ_SUCCESS) {
1364
sip_err_code = PJSIP_SC_NOT_ACCEPTABLE;
1365
/* Since the call invite's state is still PJSIP_INV_STATE_NULL,
1366
* the invite session was not ended in
1367
* on_incoming_call_med_tp_complete(), so we need to send
1368
* a response message and terminate the invite here.
1370
pjsip_dlg_respond(dlg, rdata, sip_err_code, NULL, NULL, NULL);
1371
pjsip_inv_terminate(call->inv, sip_err_code, PJ_FALSE);
1375
} else if (status != PJ_EPENDING) {
1376
pjsua_perror(THIS_FILE, "Error initializing media channel", status);
1377
pjsip_dlg_respond(dlg, rdata, sip_err_code, NULL, NULL, NULL);
1378
pjsip_inv_terminate(call->inv, sip_err_code, PJ_FALSE);
1386
status = pjsua_media_channel_create_sdp(call->index, rdata->tp_info.pool,
1387
offer, &answer, &sip_err_code);
1388
if (status != PJ_SUCCESS) {
1389
pjsua_perror(THIS_FILE, "Error creating SDP answer", status);
1390
pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata,
1391
sip_err_code, NULL, NULL, NULL, NULL);
1396
/* Init Session Timers */
1397
status = pjsip_timer_init_session(inv,
1398
&pjsua_var.acc[acc_id].cfg.timer_setting);
1399
if (status != PJ_SUCCESS) {
1400
pjsua_perror(THIS_FILE, "Session Timer init failed", status);
1401
pjsip_dlg_respond(dlg, rdata, PJSIP_SC_INTERNAL_SERVER_ERROR, NULL, NULL, NULL);
1402
pjsip_inv_terminate(inv, PJSIP_SC_INTERNAL_SERVER_ERROR, PJ_FALSE);
1404
pjsua_media_channel_deinit(call->index);
1410
/* Update NAT type of remote endpoint, only when there is SDP in
1413
if (pjsua_var.ua_cfg.nat_type_in_sdp && inv->neg &&
1414
pjmedia_sdp_neg_get_state(inv->neg) > PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER)
1416
const pjmedia_sdp_session *remote_sdp;
1418
if (pjmedia_sdp_neg_get_neg_remote(inv->neg, &remote_sdp)==PJ_SUCCESS)
1419
update_remote_nat_type(call, remote_sdp);
1422
/* Must answer with some response to initial INVITE. We'll do this before
1423
* attaching the call to the invite session/dialog, so that the application
1424
* will not get notification about this event (on another scenario, it is
1425
* also possible that inv_send_msg() fails and causes the invite session to
1426
* be disconnected. If we have the call attached at this time, this will
1427
* cause the disconnection callback to be called before on_incoming_call()
1428
* callback is called, which is not right).
1430
status = pjsip_inv_initial_answer(inv, rdata,
1431
100, NULL, NULL, &response);
1432
if (status != PJ_SUCCESS) {
1433
if (response == NULL) {
1434
pjsua_perror(THIS_FILE, "Unable to send answer to incoming INVITE",
1436
pjsip_dlg_respond(dlg, rdata, 500, NULL, NULL, NULL);
1437
pjsip_inv_terminate(inv, 500, PJ_FALSE);
1439
pjsip_inv_send_msg(inv, response);
1440
pjsip_inv_terminate(inv, response->msg->line.status.code,
1443
pjsua_media_channel_deinit(call->index);
1448
status = pjsip_inv_send_msg(inv, response);
1449
if (status != PJ_SUCCESS) {
1450
pjsua_perror(THIS_FILE, "Unable to send 100 response", status);
1451
pjsua_media_channel_deinit(call->index);
1457
/* Only do this after sending 100/Trying (really! see the long comment
1460
dlg->mod_data[pjsua_var.mod.id] = call;
1461
inv->mod_data[pjsua_var.mod.id] = call;
1463
++pjsua_var.call_cnt;
1465
/* Check if this request should replace existing call */
1467
/* Process call replace. If the media channel init has been completed,
1468
* just process now, otherwise, just queue the replaced dialog so
1469
* it will be processed once the media channel async init is finished
1472
if (call->med_ch_cb == NULL) {
1473
process_incoming_call_replace(call, replaced_dlg);
1475
call->async_call.call_var.inc_call.replaced_dlg = replaced_dlg;
1478
/* Notify application if on_incoming_call() is overriden,
1479
* otherwise hangup the call with 480
1481
if (pjsua_var.ua_cfg.cb.on_incoming_call) {
1482
pjsua_var.ua_cfg.cb.on_incoming_call(acc_id, call_id, rdata);
1484
pjsua_call_hangup(call_id, PJSIP_SC_TEMPORARILY_UNAVAILABLE,
1490
/* This INVITE request has been handled. */
1492
pj_log_pop_indent();
1500
* Check if the specified call has active INVITE session and the INVITE
1501
* session has not been disconnected.
1503
PJ_DEF(pj_bool_t) pjsua_call_is_active(pjsua_call_id call_id)
1505
PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
1507
return pjsua_var.calls[call_id].inv != NULL &&
1508
pjsua_var.calls[call_id].inv->state != PJSIP_INV_STATE_DISCONNECTED;
1512
/* Acquire lock to the specified call_id */
1513
pj_status_t acquire_call(const char *title,
1514
pjsua_call_id call_id,
1515
pjsua_call **p_call,
1516
pjsip_dialog **p_dlg)
1519
pjsua_call *call = NULL;
1520
pj_bool_t has_pjsua_lock = PJ_FALSE;
1521
pj_status_t status = PJ_SUCCESS;
1522
pj_time_val time_start, timeout;
1523
pjsip_dialog *dlg = NULL;
1525
pj_gettimeofday(&time_start);
1527
timeout.msec = PJSUA_ACQUIRE_CALL_TIMEOUT;
1528
pj_time_val_normalize(&timeout);
1530
for (retry=0; ; ++retry) {
1532
if (retry % 10 == 9) {
1535
pj_gettimeofday(&dtime);
1536
PJ_TIME_VAL_SUB(dtime, time_start);
1537
if (!PJ_TIME_VAL_LT(dtime, timeout))
1541
has_pjsua_lock = PJ_FALSE;
1543
status = PJSUA_TRY_LOCK();
1544
if (status != PJ_SUCCESS) {
1545
pj_thread_sleep(retry/10);
1549
has_pjsua_lock = PJ_TRUE;
1550
call = &pjsua_var.calls[call_id];
1552
dlg = call->inv->dlg;
1554
dlg = call->async_call.dlg;
1558
PJ_LOG(3,(THIS_FILE, "Invalid call_id %d in %s", call_id, title));
1559
return PJSIP_ESESSIONTERMINATED;
1562
status = pjsip_dlg_try_inc_lock(dlg);
1563
if (status != PJ_SUCCESS) {
1565
pj_thread_sleep(retry/10);
1574
if (status != PJ_SUCCESS) {
1575
if (has_pjsua_lock == PJ_FALSE)
1576
PJ_LOG(1,(THIS_FILE, "Timed-out trying to acquire PJSUA mutex "
1577
"(possibly system has deadlocked) in %s",
1580
PJ_LOG(1,(THIS_FILE, "Timed-out trying to acquire dialog mutex "
1581
"(possibly system has deadlocked) in %s",
1583
return PJ_ETIMEDOUT;
1594
* Obtain detail information about the specified call.
1596
PJ_DEF(pj_status_t) pjsua_call_get_info( pjsua_call_id call_id,
1597
pjsua_call_info *info)
1603
PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
1606
pj_bzero(info, sizeof(*info));
1608
/* Use PJSUA_LOCK() instead of acquire_call():
1609
* https://trac.pjsip.org/repos/ticket/1371
1613
call = &pjsua_var.calls[call_id];
1614
dlg = (call->inv ? call->inv->dlg : call->async_call.dlg);
1617
return PJSIP_ESESSIONTERMINATED;
1622
info->role = dlg->role;
1623
info->acc_id = call->acc_id;
1626
info->local_info.ptr = info->buf_.local_info;
1627
pj_strncpy(&info->local_info, &dlg->local.info_str,
1628
sizeof(info->buf_.local_info));
1631
info->local_contact.ptr = info->buf_.local_contact;
1632
info->local_contact.slen = pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR,
1633
dlg->local.contact->uri,
1634
info->local_contact.ptr,
1635
sizeof(info->buf_.local_contact));
1638
info->remote_info.ptr = info->buf_.remote_info;
1639
pj_strncpy(&info->remote_info, &dlg->remote.info_str,
1640
sizeof(info->buf_.remote_info));
1642
/* remote contact */
1643
if (dlg->remote.contact) {
1645
info->remote_contact.ptr = info->buf_.remote_contact;
1646
len = pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR,
1647
dlg->remote.contact->uri,
1648
info->remote_contact.ptr,
1649
sizeof(info->buf_.remote_contact));
1650
if (len < 0) len = 0;
1651
info->remote_contact.slen = len;
1653
info->remote_contact.slen = 0;
1657
info->call_id.ptr = info->buf_.call_id;
1658
pj_strncpy(&info->call_id, &dlg->call_id->id,
1659
sizeof(info->buf_.call_id));
1662
pj_memcpy(&info->setting, &call->opt, sizeof(call->opt));
1664
/* state, state_text */
1666
info->state = call->inv->state;
1667
} else if (call->async_call.dlg && call->last_code==0) {
1668
info->state = PJSIP_INV_STATE_NULL;
1670
info->state = PJSIP_INV_STATE_DISCONNECTED;
1672
info->state_text = pj_str((char*)pjsip_inv_state_name(info->state));
1674
/* If call is disconnected, set the last_status from the cause code */
1675
if (call->inv && call->inv->state >= PJSIP_INV_STATE_DISCONNECTED) {
1676
/* last_status, last_status_text */
1677
info->last_status = call->inv->cause;
1679
info->last_status_text.ptr = info->buf_.last_status_text;
1680
pj_strncpy(&info->last_status_text, &call->inv->cause_text,
1681
sizeof(info->buf_.last_status_text));
1683
/* last_status, last_status_text */
1684
info->last_status = call->last_code;
1686
info->last_status_text.ptr = info->buf_.last_status_text;
1687
pj_strncpy(&info->last_status_text, &call->last_text,
1688
sizeof(info->buf_.last_status_text));
1691
/* Audio & video count offered by remote */
1692
info->rem_offerer = call->rem_offerer;
1693
if (call->rem_offerer) {
1694
info->rem_aud_cnt = call->rem_aud_cnt;
1695
info->rem_vid_cnt = call->rem_vid_cnt;
1698
/* Build array of active media info */
1699
info->media_cnt = 0;
1700
for (mi=0; mi < call->med_cnt &&
1701
info->media_cnt < PJ_ARRAY_SIZE(info->media); ++mi)
1703
pjsua_call_media *call_med = &call->media[mi];
1705
info->media[info->media_cnt].index = mi;
1706
info->media[info->media_cnt].status = call_med->state;
1707
info->media[info->media_cnt].dir = call_med->dir;
1708
info->media[info->media_cnt].type = call_med->type;
1710
if (call_med->type == PJMEDIA_TYPE_AUDIO) {
1711
info->media[info->media_cnt].stream.aud.conf_slot =
1712
call_med->strm.a.conf_slot;
1713
} else if (call_med->type == PJMEDIA_TYPE_VIDEO) {
1714
pjmedia_vid_dev_index cap_dev = PJMEDIA_VID_INVALID_DEV;
1716
info->media[info->media_cnt].stream.vid.win_in =
1717
call_med->strm.v.rdr_win_id;
1719
if (call_med->strm.v.cap_win_id != PJSUA_INVALID_ID) {
1720
cap_dev = call_med->strm.v.cap_dev;
1722
info->media[info->media_cnt].stream.vid.cap_dev = cap_dev;
1729
if (call->audio_idx != -1) {
1730
info->media_status = call->media[call->audio_idx].state;
1731
info->media_dir = call->media[call->audio_idx].dir;
1732
info->conf_slot = call->media[call->audio_idx].strm.a.conf_slot;
1735
/* Build array of provisional media info */
1736
info->prov_media_cnt = 0;
1737
for (mi=0; mi < call->med_prov_cnt &&
1738
info->prov_media_cnt < PJ_ARRAY_SIZE(info->prov_media); ++mi)
1740
pjsua_call_media *call_med = &call->media_prov[mi];
1742
info->prov_media[info->prov_media_cnt].index = mi;
1743
info->prov_media[info->prov_media_cnt].status = call_med->state;
1744
info->prov_media[info->prov_media_cnt].dir = call_med->dir;
1745
info->prov_media[info->prov_media_cnt].type = call_med->type;
1746
if (call_med->type == PJMEDIA_TYPE_AUDIO) {
1747
info->prov_media[info->prov_media_cnt].stream.aud.conf_slot =
1748
call_med->strm.a.conf_slot;
1749
} else if (call_med->type == PJMEDIA_TYPE_VIDEO) {
1750
pjmedia_vid_dev_index cap_dev = PJMEDIA_VID_INVALID_DEV;
1752
info->prov_media[info->prov_media_cnt].stream.vid.win_in =
1753
call_med->strm.v.rdr_win_id;
1755
if (call_med->strm.v.cap_win_id != PJSUA_INVALID_ID) {
1756
cap_dev = call_med->strm.v.cap_dev;
1758
info->prov_media[info->prov_media_cnt].stream.vid.cap_dev=cap_dev;
1762
++info->prov_media_cnt;
1765
/* calculate duration */
1766
if (info->state >= PJSIP_INV_STATE_DISCONNECTED) {
1768
info->total_duration = call->dis_time;
1769
PJ_TIME_VAL_SUB(info->total_duration, call->start_time);
1771
if (call->conn_time.sec) {
1772
info->connect_duration = call->dis_time;
1773
PJ_TIME_VAL_SUB(info->connect_duration, call->conn_time);
1776
} else if (info->state == PJSIP_INV_STATE_CONFIRMED) {
1778
pj_gettimeofday(&info->total_duration);
1779
PJ_TIME_VAL_SUB(info->total_duration, call->start_time);
1781
pj_gettimeofday(&info->connect_duration);
1782
PJ_TIME_VAL_SUB(info->connect_duration, call->conn_time);
1785
pj_gettimeofday(&info->total_duration);
1786
PJ_TIME_VAL_SUB(info->total_duration, call->start_time);
1795
* Check if call remote peer support the specified capability.
1797
PJ_DEF(pjsip_dialog_cap_status) pjsua_call_remote_has_cap(
1798
pjsua_call_id call_id,
1800
const pj_str_t *hname,
1801
const pj_str_t *token)
1806
pjsip_dialog_cap_status cap_status;
1808
status = acquire_call("pjsua_call_peer_has_cap()", call_id, &call, &dlg);
1809
if (status != PJ_SUCCESS)
1810
return PJSIP_DIALOG_CAP_UNKNOWN;
1812
cap_status = pjsip_dlg_remote_has_cap(dlg, htype, hname, token);
1814
pjsip_dlg_dec_lock(dlg);
1821
* Attach application specific data to the call.
1823
PJ_DEF(pj_status_t) pjsua_call_set_user_data( pjsua_call_id call_id,
1826
PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
1828
pjsua_var.calls[call_id].user_data = user_data;
1835
* Get user data attached to the call.
1837
PJ_DEF(void*) pjsua_call_get_user_data(pjsua_call_id call_id)
1839
PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
1841
return pjsua_var.calls[call_id].user_data;
1846
* Get remote's NAT type.
1848
PJ_DEF(pj_status_t) pjsua_call_get_rem_nat_type(pjsua_call_id call_id,
1849
pj_stun_nat_type *p_type)
1851
PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
1853
PJ_ASSERT_RETURN(p_type != NULL, PJ_EINVAL);
1855
*p_type = pjsua_var.calls[call_id].rem_nat_type;
1861
* Get media transport info for the specified media index.
1864
pjsua_call_get_med_transport_info(pjsua_call_id call_id,
1866
pjmedia_transport_info *t)
1869
pjsua_call_media *call_med;
1872
PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
1874
PJ_ASSERT_RETURN(t, PJ_EINVAL);
1878
call = &pjsua_var.calls[call_id];
1880
if (med_idx >= call->med_cnt) {
1885
call_med = &call->media[med_idx];
1887
pjmedia_transport_info_init(t);
1888
status = pjmedia_transport_get_info(call_med->tp, t);
1895
/* Media channel init callback for pjsua_call_answer(). */
1897
on_answer_call_med_tp_complete(pjsua_call_id call_id,
1898
const pjsua_med_tp_state_info *info)
1900
pjsua_call *call = &pjsua_var.calls[call_id];
1901
pjmedia_sdp_session *sdp;
1902
int sip_err_code = (info? info->sip_err_code: 0);
1903
pj_status_t status = (info? info->status: PJ_SUCCESS);
1907
if (status != PJ_SUCCESS) {
1908
pjsua_perror(THIS_FILE, "Error initializing media channel", status);
1912
/* pjsua_media_channel_deinit() has been called. */
1913
if (call->async_call.med_ch_deinit) {
1914
pjsua_media_channel_deinit(call->index);
1915
call->med_ch_cb = NULL;
1920
status = pjsua_media_channel_create_sdp(call_id,
1921
call->async_call.dlg->pool,
1922
NULL, &sdp, &sip_err_code);
1923
if (status != PJ_SUCCESS) {
1924
pjsua_perror(THIS_FILE, "Error creating SDP answer", status);
1928
status = pjsip_inv_set_local_sdp(call->inv, sdp);
1929
if (status != PJ_SUCCESS) {
1930
pjsua_perror(THIS_FILE, "Error setting local SDP", status);
1931
sip_err_code = PJSIP_SC_NOT_ACCEPTABLE_HERE;
1936
if (status != PJ_SUCCESS) {
1937
/* If the callback is called from pjsua_call_on_incoming(), the
1938
* invite's state is PJSIP_INV_STATE_NULL, so the invite session
1939
* will be terminated later, otherwise we end the session here.
1941
if (call->inv->state > PJSIP_INV_STATE_NULL) {
1942
pjsip_tx_data *tdata;
1943
pj_status_t status_;
1945
status_ = pjsip_inv_end_session(call->inv, sip_err_code, NULL,
1947
if (status_ == PJ_SUCCESS && tdata)
1948
status_ = pjsip_inv_send_msg(call->inv, tdata);
1951
pjsua_media_channel_deinit(call->index);
1954
/* Set the callback to NULL to indicate that the async operation
1957
call->med_ch_cb = NULL;
1959
/* Finish any pending process */
1960
if (status == PJ_SUCCESS) {
1961
/* Process pending call answers */
1962
process_pending_call_answer(call);
1971
* Send response to incoming INVITE request.
1973
PJ_DEF(pj_status_t) pjsua_call_answer( pjsua_call_id call_id,
1975
const pj_str_t *reason,
1976
const pjsua_msg_data *msg_data)
1978
return pjsua_call_answer2(call_id, NULL, code, reason, msg_data);
1983
* Send response to incoming INVITE request.
1985
PJ_DEF(pj_status_t) pjsua_call_answer2(pjsua_call_id call_id,
1986
const pjsua_call_setting *opt,
1988
const pj_str_t *reason,
1989
const pjsua_msg_data *msg_data)
1992
pjsip_dialog *dlg = NULL;
1993
pjsip_tx_data *tdata;
1996
PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
1999
PJ_LOG(4,(THIS_FILE, "Answering call %d: code=%d", call_id, code));
2000
pj_log_push_indent();
2002
status = acquire_call("pjsua_call_answer()", call_id, &call, &dlg);
2003
if (status != PJ_SUCCESS)
2006
/* Apply call setting, only if status code is 1xx or 2xx. */
2007
if (opt && code < 300) {
2008
/* Check if it has not been set previously or it is different to
2011
if (!call->opt_inited) {
2012
call->opt_inited = PJ_TRUE;
2013
apply_call_setting(call, opt, NULL);
2014
} else if (pj_memcmp(opt, &call->opt, sizeof(*opt)) != 0) {
2015
/* Warn application about call setting inconsistency */
2016
PJ_LOG(2,(THIS_FILE, "The call setting changes is ignored."));
2022
/* Ticket #1526: When the incoming call contains no SDP offer, the media
2023
* channel may have not been initialized at this stage. The media channel
2024
* will be initialized here (along with SDP local offer generation) when
2025
* the following conditions are met:
2026
* - no pending media channel init
2027
* - local SDP has not been generated
2028
* - call setting has just been set, or SDP offer needs to be sent, i.e:
2029
* answer code 183 or 2xx is issued
2031
if (!call->med_ch_cb &&
2032
(call->opt_inited || (code==183 || code/100==2)) &&
2034
pjmedia_sdp_neg_get_state(call->inv->neg) ==
2035
PJMEDIA_SDP_NEG_STATE_NULL))
2037
/* Mark call setting as initialized as it is just about to be used
2038
* for initializing the media channel.
2040
call->opt_inited = PJ_TRUE;
2042
status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAC,
2045
NULL, NULL, PJ_TRUE,
2046
&on_answer_call_med_tp_complete);
2047
if (status == PJ_SUCCESS) {
2048
status = on_answer_call_med_tp_complete(call->index, NULL);
2049
if (status != PJ_SUCCESS) {
2053
} else if (status != PJ_EPENDING) {
2055
pjsua_perror(THIS_FILE, "Error initializing media channel", status);
2060
/* If media transport creation is not yet completed, we will answer
2061
* the call in the media transport creation callback instead.
2063
if (call->med_ch_cb) {
2064
struct call_answer *answer;
2066
PJ_LOG(4,(THIS_FILE, "Pending answering call %d upon completion "
2067
"of media transport", call_id));
2069
answer = PJ_POOL_ZALLOC_T(call->inv->pool_prov, struct call_answer);
2070
answer->code = code;
2072
answer->opt = PJ_POOL_ZALLOC_T(call->inv->pool_prov,
2073
pjsua_call_setting);
2074
*answer->opt = *opt;
2077
pj_strdup(call->inv->pool_prov, answer->reason, reason);
2080
answer->msg_data = pjsua_msg_data_clone(call->inv->pool_prov,
2083
pj_list_push_back(&call->async_call.call_var.inc_call.answers,
2087
if (dlg) pjsip_dlg_dec_lock(dlg);
2088
pj_log_pop_indent();
2094
if (call->res_time.sec == 0)
2095
pj_gettimeofday(&call->res_time);
2097
if (reason && reason->slen == 0)
2100
/* Create response message */
2101
status = pjsip_inv_answer(call->inv, code, reason, NULL, &tdata);
2102
if (status != PJ_SUCCESS) {
2103
pjsua_perror(THIS_FILE, "Error creating response",
2108
/* Call might have been disconnected if application is answering with
2109
* 200/OK and the media failed to start.
2111
if (call->inv == NULL)
2114
/* Add additional headers etc */
2115
pjsua_process_msg_data( tdata, msg_data);
2117
/* Send the message */
2118
status = pjsip_inv_send_msg(call->inv, tdata);
2119
if (status != PJ_SUCCESS)
2120
pjsua_perror(THIS_FILE, "Error sending response",
2124
if (dlg) pjsip_dlg_dec_lock(dlg);
2125
pj_log_pop_indent();
2131
* Hangup call by using method that is appropriate according to the
2134
PJ_DEF(pj_status_t) pjsua_call_hangup(pjsua_call_id call_id,
2136
const pj_str_t *reason,
2137
const pjsua_msg_data *msg_data)
2140
pjsip_dialog *dlg = NULL;
2142
pjsip_tx_data *tdata;
2145
if (call_id<0 || call_id>=(int)pjsua_var.ua_cfg.max_calls) {
2146
PJ_LOG(1,(THIS_FILE, "pjsua_call_hangup(): invalid call id %d",
2150
PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
2153
PJ_LOG(4,(THIS_FILE, "Call %d hanging up: code=%d..", call_id, code));
2154
pj_log_push_indent();
2156
status = acquire_call("pjsua_call_hangup()", call_id, &call, &dlg);
2157
if (status != PJ_SUCCESS)
2160
/* If media transport creation is not yet completed, we will hangup
2161
* the call in the media transport creation callback instead.
2163
if (call->med_ch_cb && !call->inv) {
2164
PJ_LOG(4,(THIS_FILE, "Pending call %d hangup upon completion "
2165
"of media transport", call_id));
2166
call->async_call.call_var.out_call.hangup = PJ_TRUE;
2168
call->last_code = PJSIP_SC_REQUEST_TERMINATED;
2170
call->last_code = (pjsip_status_code)code;
2172
pj_strncpy(&call->last_text, reason,
2173
sizeof(call->last_text_buf_));
2180
if (call->inv->state == PJSIP_INV_STATE_CONFIRMED)
2182
else if (call->inv->role == PJSIP_ROLE_UAS)
2183
code = PJSIP_SC_DECLINE;
2185
code = PJSIP_SC_REQUEST_TERMINATED;
2188
status = pjsip_inv_end_session(call->inv, code, reason, &tdata);
2189
if (status != PJ_SUCCESS) {
2190
pjsua_perror(THIS_FILE,
2191
"Failed to create end session message",
2196
/* pjsip_inv_end_session may return PJ_SUCCESS with NULL
2197
* as p_tdata when INVITE transaction has not been answered
2198
* with any provisional responses.
2203
/* Add additional headers etc */
2204
pjsua_process_msg_data( tdata, msg_data);
2206
/* Send the message */
2207
status = pjsip_inv_send_msg(call->inv, tdata);
2208
if (status != PJ_SUCCESS) {
2209
pjsua_perror(THIS_FILE,
2210
"Failed to send end session message",
2215
/* Stop reinvite timer, if it is active */
2216
if (call->reinv_timer.id) {
2217
pjsua_cancel_timer(&call->reinv_timer);
2218
call->reinv_timer.id = PJ_FALSE;
2222
if (dlg) pjsip_dlg_dec_lock(dlg);
2223
pj_log_pop_indent();
2229
* Accept or reject redirection.
2231
PJ_DEF(pj_status_t) pjsua_call_process_redirect( pjsua_call_id call_id,
2232
pjsip_redirect_op cmd)
2238
PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
2241
status = acquire_call("pjsua_call_process_redirect()", call_id,
2243
if (status != PJ_SUCCESS)
2246
status = pjsip_inv_process_redirect(call->inv, cmd, NULL);
2248
pjsip_dlg_dec_lock(dlg);
2255
* Put the specified call on hold.
2257
PJ_DEF(pj_status_t) pjsua_call_set_hold(pjsua_call_id call_id,
2258
const pjsua_msg_data *msg_data)
2260
pjmedia_sdp_session *sdp;
2262
pjsip_dialog *dlg = NULL;
2263
pjsip_tx_data *tdata;
2266
PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
2269
PJ_LOG(4,(THIS_FILE, "Putting call %d on hold", call_id));
2270
pj_log_push_indent();
2272
status = acquire_call("pjsua_call_set_hold()", call_id, &call, &dlg);
2273
if (status != PJ_SUCCESS)
2276
if (call->inv->state != PJSIP_INV_STATE_CONFIRMED) {
2277
PJ_LOG(3,(THIS_FILE, "Can not hold call that is not confirmed"));
2278
status = PJSIP_ESESSIONSTATE;
2282
status = create_sdp_of_call_hold(call, &sdp);
2283
if (status != PJ_SUCCESS)
2286
/* Create re-INVITE with new offer */
2287
status = pjsip_inv_reinvite( call->inv, NULL, sdp, &tdata);
2288
if (status != PJ_SUCCESS) {
2289
pjsua_perror(THIS_FILE, "Unable to create re-INVITE", status);
2293
/* Add additional headers etc */
2294
pjsua_process_msg_data( tdata, msg_data);
2296
/* Record the tx_data to keep track the operation */
2297
call->hold_msg = (void*) tdata;
2299
/* Send the request */
2300
status = pjsip_inv_send_msg( call->inv, tdata);
2301
if (status != PJ_SUCCESS) {
2302
pjsua_perror(THIS_FILE, "Unable to send re-INVITE", status);
2303
call->hold_msg = NULL;
2307
/* Set flag that local put the call on hold */
2308
call->local_hold = PJ_TRUE;
2311
if (dlg) pjsip_dlg_dec_lock(dlg);
2312
pj_log_pop_indent();
2318
* Send re-INVITE (to release hold).
2320
PJ_DEF(pj_status_t) pjsua_call_reinvite( pjsua_call_id call_id,
2322
const pjsua_msg_data *msg_data)
2325
pjsip_dialog *dlg = NULL;
2328
status = acquire_call("pjsua_call_reinvite()", call_id, &call, &dlg);
2329
if (status != PJ_SUCCESS)
2332
if (options != call->opt.flag)
2333
call->opt.flag = options;
2335
status = pjsua_call_reinvite2(call_id, NULL, msg_data);
2338
if (dlg) pjsip_dlg_dec_lock(dlg);
2344
* Send re-INVITE (to release hold).
2346
PJ_DEF(pj_status_t) pjsua_call_reinvite2(pjsua_call_id call_id,
2347
const pjsua_call_setting *opt,
2348
const pjsua_msg_data *msg_data)
2350
pjmedia_sdp_session *sdp;
2351
pj_str_t *new_contact = NULL;
2352
pjsip_tx_data *tdata;
2354
pjsip_dialog *dlg = NULL;
2358
PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
2361
PJ_LOG(4,(THIS_FILE, "Sending re-INVITE on call %d", call_id));
2362
pj_log_push_indent();
2364
status = acquire_call("pjsua_call_reinvite2()", call_id, &call, &dlg);
2365
if (status != PJ_SUCCESS)
2368
if (call->inv->state != PJSIP_INV_STATE_CONFIRMED) {
2369
PJ_LOG(3,(THIS_FILE, "Can not re-INVITE call that is not confirmed"));
2370
status = PJSIP_ESESSIONSTATE;
2374
status = apply_call_setting(call, opt, NULL);
2375
if (status != PJ_SUCCESS) {
2376
pjsua_perror(THIS_FILE, "Failed to apply call setting", status);
2381
if (call->local_hold && (call->opt.flag & PJSUA_CALL_UNHOLD)==0) {
2382
status = create_sdp_of_call_hold(call, &sdp);
2384
status = pjsua_media_channel_create_sdp(call->index,
2385
call->inv->pool_prov,
2387
call->local_hold = PJ_FALSE;
2389
if (status != PJ_SUCCESS) {
2390
pjsua_perror(THIS_FILE, "Unable to get SDP from media endpoint",
2395
if ((call->opt.flag & PJSUA_CALL_UPDATE_CONTACT) &&
2396
pjsua_acc_is_valid(call->acc_id))
2398
new_contact = &pjsua_var.acc[call->acc_id].contact;
2401
/* Create re-INVITE with new offer */
2402
status = pjsip_inv_reinvite( call->inv, new_contact, sdp, &tdata);
2403
if (status != PJ_SUCCESS) {
2404
pjsua_perror(THIS_FILE, "Unable to create re-INVITE", status);
2408
/* Add additional headers etc */
2409
pjsua_process_msg_data( tdata, msg_data);
2411
/* Send the request */
2412
status = pjsip_inv_send_msg( call->inv, tdata);
2413
if (status != PJ_SUCCESS) {
2414
pjsua_perror(THIS_FILE, "Unable to send re-INVITE", status);
2419
if (dlg) pjsip_dlg_dec_lock(dlg);
2420
pj_log_pop_indent();
2426
* Send UPDATE request.
2428
PJ_DEF(pj_status_t) pjsua_call_update( pjsua_call_id call_id,
2430
const pjsua_msg_data *msg_data)
2433
pjsip_dialog *dlg = NULL;
2436
status = acquire_call("pjsua_call_update()", call_id, &call, &dlg);
2437
if (status != PJ_SUCCESS)
2440
if (options != call->opt.flag)
2441
call->opt.flag = options;
2443
status = pjsua_call_update2(call_id, NULL, msg_data);
2446
if (dlg) pjsip_dlg_dec_lock(dlg);
2452
* Send UPDATE request.
2454
PJ_DEF(pj_status_t) pjsua_call_update2(pjsua_call_id call_id,
2455
const pjsua_call_setting *opt,
2456
const pjsua_msg_data *msg_data)
2458
pjmedia_sdp_session *sdp;
2459
pj_str_t *new_contact = NULL;
2460
pjsip_tx_data *tdata;
2462
pjsip_dialog *dlg = NULL;
2465
PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
2468
PJ_LOG(4,(THIS_FILE, "Sending UPDATE on call %d", call_id));
2469
pj_log_push_indent();
2471
status = acquire_call("pjsua_call_update2()", call_id, &call, &dlg);
2472
if (status != PJ_SUCCESS)
2475
status = apply_call_setting(call, opt, NULL);
2476
if (status != PJ_SUCCESS) {
2477
pjsua_perror(THIS_FILE, "Failed to apply call setting", status);
2482
status = pjsua_media_channel_create_sdp(call->index,
2483
call->inv->pool_prov,
2485
if (status != PJ_SUCCESS) {
2486
pjsua_perror(THIS_FILE, "Unable to get SDP from media endpoint",
2491
if ((call->opt.flag & PJSUA_CALL_UPDATE_CONTACT) &&
2492
pjsua_acc_is_valid(call->acc_id))
2494
new_contact = &pjsua_var.acc[call->acc_id].contact;
2497
/* Create UPDATE with new offer */
2498
status = pjsip_inv_update(call->inv, new_contact, sdp, &tdata);
2499
if (status != PJ_SUCCESS) {
2500
pjsua_perror(THIS_FILE, "Unable to create UPDATE request", status);
2504
/* Add additional headers etc */
2505
pjsua_process_msg_data( tdata, msg_data);
2507
/* Send the request */
2508
status = pjsip_inv_send_msg( call->inv, tdata);
2509
if (status != PJ_SUCCESS) {
2510
pjsua_perror(THIS_FILE, "Unable to send UPDATE request", status);
2514
call->local_hold = PJ_FALSE;
2517
if (dlg) pjsip_dlg_dec_lock(dlg);
2518
pj_log_pop_indent();
2524
* Initiate call transfer to the specified address.
2526
PJ_DEF(pj_status_t) pjsua_call_xfer( pjsua_call_id call_id,
2527
const pj_str_t *dest,
2528
const pjsua_msg_data *msg_data)
2531
pjsip_tx_data *tdata;
2533
pjsip_dialog *dlg = NULL;
2534
pjsip_generic_string_hdr *gs_hdr;
2535
const pj_str_t str_ref_by = { "Referred-By", 11 };
2536
struct pjsip_evsub_user xfer_cb;
2540
PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls &&
2543
PJ_LOG(4,(THIS_FILE, "Transfering call %d to %.*s", call_id,
2544
(int)dest->slen, dest->ptr));
2545
pj_log_push_indent();
2547
status = acquire_call("pjsua_call_xfer()", call_id, &call, &dlg);
2548
if (status != PJ_SUCCESS)
2551
/* Create xfer client subscription. */
2552
pj_bzero(&xfer_cb, sizeof(xfer_cb));
2553
xfer_cb.on_evsub_state = &xfer_client_on_evsub_state;
2555
status = pjsip_xfer_create_uac(call->inv->dlg, &xfer_cb, &sub);
2556
if (status != PJ_SUCCESS) {
2557
pjsua_perror(THIS_FILE, "Unable to create xfer", status);
2561
/* Associate this call with the client subscription */
2562
pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, call);
2565
* Create REFER request.
2567
status = pjsip_xfer_initiate(sub, dest, &tdata);
2568
if (status != PJ_SUCCESS) {
2569
pjsua_perror(THIS_FILE, "Unable to create REFER request", status);
2573
/* Add Referred-By header */
2574
gs_hdr = pjsip_generic_string_hdr_create(tdata->pool, &str_ref_by,
2575
&dlg->local.info_str);
2576
pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)gs_hdr);
2579
/* Add additional headers etc */
2580
pjsua_process_msg_data( tdata, msg_data);
2583
status = pjsip_xfer_send_request(sub, tdata);
2584
if (status != PJ_SUCCESS) {
2585
pjsua_perror(THIS_FILE, "Unable to send REFER request", status);
2589
/* For simplicity (that's what this program is intended to be!),
2590
* leave the original invite session as it is. More advanced application
2591
* may want to hold the INVITE, or terminate the invite, or whatever.
2594
if (dlg) pjsip_dlg_dec_lock(dlg);
2595
pj_log_pop_indent();
2602
* Initiate attended call transfer to the specified address.
2604
PJ_DEF(pj_status_t) pjsua_call_xfer_replaces( pjsua_call_id call_id,
2605
pjsua_call_id dest_call_id,
2607
const pjsua_msg_data *msg_data)
2609
pjsua_call *dest_call;
2610
pjsip_dialog *dest_dlg;
2611
char str_dest_buf[PJSIP_MAX_URL_SIZE*2];
2618
PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
2620
PJ_ASSERT_RETURN(dest_call_id>=0 &&
2621
dest_call_id<(int)pjsua_var.ua_cfg.max_calls,
2624
PJ_LOG(4,(THIS_FILE, "Transfering call %d replacing with call %d",
2625
call_id, dest_call_id));
2626
pj_log_push_indent();
2628
status = acquire_call("pjsua_call_xfer_replaces()", dest_call_id,
2629
&dest_call, &dest_dlg);
2630
if (status != PJ_SUCCESS) {
2631
pj_log_pop_indent();
2636
* Create REFER destination URI with Replaces field.
2639
/* Make sure we have sufficient buffer's length */
2640
PJ_ASSERT_ON_FAIL(dest_dlg->remote.info_str.slen +
2641
dest_dlg->call_id->id.slen +
2642
dest_dlg->remote.info->tag.slen +
2643
dest_dlg->local.info->tag.slen + 32
2644
< (long)sizeof(str_dest_buf),
2645
{ status=PJSIP_EURITOOLONG; goto on_error; });
2648
str_dest_buf[0] = '<';
2651
uri = (pjsip_uri*) pjsip_uri_get_uri(dest_dlg->remote.info->uri);
2652
len = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, uri,
2653
str_dest_buf+1, sizeof(str_dest_buf)-1);
2655
status = PJSIP_EURITOOLONG;
2659
str_dest.slen += len;
2663
len = pj_ansi_snprintf(str_dest_buf + str_dest.slen,
2664
sizeof(str_dest_buf) - str_dest.slen,
2667
"%%3Bto-tag%%3D%.*s"
2668
"%%3Bfrom-tag%%3D%.*s>",
2669
((options&PJSUA_XFER_NO_REQUIRE_REPLACES) ?
2670
"" : "Require=replaces&"),
2671
(int)dest_dlg->call_id->id.slen,
2672
dest_dlg->call_id->id.ptr,
2673
(int)dest_dlg->remote.info->tag.slen,
2674
dest_dlg->remote.info->tag.ptr,
2675
(int)dest_dlg->local.info->tag.slen,
2676
dest_dlg->local.info->tag.ptr);
2678
PJ_ASSERT_ON_FAIL(len > 0 && len <= (int)sizeof(str_dest_buf)-str_dest.slen,
2679
{ status=PJSIP_EURITOOLONG; goto on_error; });
2681
str_dest.ptr = str_dest_buf;
2682
str_dest.slen += len;
2684
pjsip_dlg_dec_lock(dest_dlg);
2686
status = pjsua_call_xfer(call_id, &str_dest, msg_data);
2688
pj_log_pop_indent();
2692
if (dest_dlg) pjsip_dlg_dec_lock(dest_dlg);
2693
pj_log_pop_indent();
2699
* Send instant messaging inside INVITE session.
2701
PJ_DEF(pj_status_t) pjsua_call_send_im( pjsua_call_id call_id,
2702
const pj_str_t *mime_type,
2703
const pj_str_t *content,
2704
const pjsua_msg_data *msg_data,
2708
pjsip_dialog *dlg = NULL;
2709
const pj_str_t mime_text_plain = pj_str("text/plain");
2710
pjsip_media_type ctype;
2711
pjsua_im_data *im_data;
2712
pjsip_tx_data *tdata;
2715
PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
2718
PJ_LOG(4,(THIS_FILE, "Call %d sending %d bytes MESSAGE..",
2719
call_id, (int)content->slen));
2720
pj_log_push_indent();
2722
status = acquire_call("pjsua_call_send_im()", call_id, &call, &dlg);
2723
if (status != PJ_SUCCESS)
2726
/* Set default media type if none is specified */
2727
if (mime_type == NULL) {
2728
mime_type = &mime_text_plain;
2731
/* Create request message. */
2732
status = pjsip_dlg_create_request( call->inv->dlg, &pjsip_message_method,
2734
if (status != PJ_SUCCESS) {
2735
pjsua_perror(THIS_FILE, "Unable to create MESSAGE request", status);
2739
/* Add accept header. */
2740
pjsip_msg_add_hdr( tdata->msg,
2741
(pjsip_hdr*)pjsua_im_create_accept(tdata->pool));
2743
/* Parse MIME type */
2744
pjsua_parse_media_type(tdata->pool, mime_type, &ctype);
2746
/* Create "text/plain" message body. */
2747
tdata->msg->body = pjsip_msg_body_create( tdata->pool, &ctype.type,
2748
&ctype.subtype, content);
2749
if (tdata->msg->body == NULL) {
2750
pjsua_perror(THIS_FILE, "Unable to create msg body", PJ_ENOMEM);
2751
pjsip_tx_data_dec_ref(tdata);
2755
/* Add additional headers etc */
2756
pjsua_process_msg_data( tdata, msg_data);
2758
/* Create IM data and attach to the request. */
2759
im_data = PJ_POOL_ZALLOC_T(tdata->pool, pjsua_im_data);
2760
im_data->acc_id = call->acc_id;
2761
im_data->call_id = call_id;
2762
im_data->to = call->inv->dlg->remote.info_str;
2763
pj_strdup_with_null(tdata->pool, &im_data->body, content);
2764
im_data->user_data = user_data;
2767
/* Send the request. */
2768
status = pjsip_dlg_send_request( call->inv->dlg, tdata,
2769
pjsua_var.mod.id, im_data);
2770
if (status != PJ_SUCCESS) {
2771
pjsua_perror(THIS_FILE, "Unable to send MESSAGE request", status);
2776
if (dlg) pjsip_dlg_dec_lock(dlg);
2777
pj_log_pop_indent();
2783
* Send IM typing indication inside INVITE session.
2785
PJ_DEF(pj_status_t) pjsua_call_send_typing_ind( pjsua_call_id call_id,
2786
pj_bool_t is_typing,
2787
const pjsua_msg_data*msg_data)
2790
pjsip_dialog *dlg = NULL;
2791
pjsip_tx_data *tdata;
2794
PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
2797
PJ_LOG(4,(THIS_FILE, "Call %d sending typing indication..",
2799
pj_log_push_indent();
2801
status = acquire_call("pjsua_call_send_typing_ind", call_id, &call, &dlg);
2802
if (status != PJ_SUCCESS)
2805
/* Create request message. */
2806
status = pjsip_dlg_create_request( call->inv->dlg, &pjsip_message_method,
2808
if (status != PJ_SUCCESS) {
2809
pjsua_perror(THIS_FILE, "Unable to create MESSAGE request", status);
2813
/* Create "application/im-iscomposing+xml" msg body. */
2814
tdata->msg->body = pjsip_iscomposing_create_body(tdata->pool, is_typing,
2817
/* Add additional headers etc */
2818
pjsua_process_msg_data( tdata, msg_data);
2820
/* Send the request. */
2821
status = pjsip_dlg_send_request( call->inv->dlg, tdata, -1, NULL);
2822
if (status != PJ_SUCCESS) {
2823
pjsua_perror(THIS_FILE, "Unable to send MESSAGE request", status);
2828
if (dlg) pjsip_dlg_dec_lock(dlg);
2829
pj_log_pop_indent();
2835
* Send arbitrary request.
2837
PJ_DEF(pj_status_t) pjsua_call_send_request(pjsua_call_id call_id,
2838
const pj_str_t *method_str,
2839
const pjsua_msg_data *msg_data)
2842
pjsip_dialog *dlg = NULL;
2843
pjsip_method method;
2844
pjsip_tx_data *tdata;
2847
PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
2850
PJ_LOG(4,(THIS_FILE, "Call %d sending %.*s request..",
2851
call_id, (int)method_str->slen, method_str->ptr));
2852
pj_log_push_indent();
2854
status = acquire_call("pjsua_call_send_request", call_id, &call, &dlg);
2855
if (status != PJ_SUCCESS)
2859
pjsip_method_init_np(&method, (pj_str_t*)method_str);
2861
/* Create request message. */
2862
status = pjsip_dlg_create_request( call->inv->dlg, &method, -1, &tdata);
2863
if (status != PJ_SUCCESS) {
2864
pjsua_perror(THIS_FILE, "Unable to create request", status);
2868
/* Add additional headers etc */
2869
pjsua_process_msg_data( tdata, msg_data);
2871
/* Send the request. */
2872
status = pjsip_dlg_send_request( call->inv->dlg, tdata, -1, NULL);
2873
if (status != PJ_SUCCESS) {
2874
pjsua_perror(THIS_FILE, "Unable to send request", status);
2879
if (dlg) pjsip_dlg_dec_lock(dlg);
2880
pj_log_pop_indent();
2886
* Terminate all calls.
2888
PJ_DEF(void) pjsua_call_hangup_all(void)
2892
PJ_LOG(4,(THIS_FILE, "Hangup all calls.."));
2893
pj_log_push_indent();
2895
// This may deadlock, see https://trac.pjsip.org/repos/ticket/1305
2898
for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) {
2899
if (pjsua_var.calls[i].inv)
2900
pjsua_call_hangup(i, 0, NULL, NULL);
2904
pj_log_pop_indent();
2908
/* Timer callback to send re-INVITE/UPDATE to lock codec or ICE update */
2909
static void reinv_timer_cb(pj_timer_heap_t *th, pj_timer_entry *entry)
2911
pjsua_call_id call_id = (pjsua_call_id)(pj_size_t)entry->user_data;
2918
pjsua_var.calls[call_id].reinv_timer.id = PJ_FALSE;
2920
pj_log_push_indent();
2922
status = acquire_call("reinv_timer_cb()", call_id, &call, &dlg);
2923
if (status != PJ_SUCCESS) {
2924
pj_log_pop_indent();
2928
process_pending_reinvite(call);
2930
pjsip_dlg_dec_lock(dlg);
2932
pj_log_pop_indent();
2936
/* Check if the specified format can be skipped in counting codecs */
2937
static pj_bool_t is_non_av_fmt(const pjmedia_sdp_media *m,
2938
const pj_str_t *fmt)
2940
const pj_str_t STR_TEL = {"telephone-event", 15};
2943
pt = pj_strtoul(fmt);
2945
/* Check for comfort noise */
2946
if (pt == PJMEDIA_RTP_PT_CN)
2949
/* Dynamic PT, check the format name */
2951
pjmedia_sdp_attr *a;
2952
pjmedia_sdp_rtpmap rtpmap;
2954
/* Get the format name */
2955
a = pjmedia_sdp_attr_find2(m->attr_count, m->attr, "rtpmap", fmt);
2956
if (a && pjmedia_sdp_attr_get_rtpmap(a, &rtpmap)==PJ_SUCCESS) {
2957
/* Check for telephone-event */
2958
if (pj_stricmp(&rtpmap.enc_name, &STR_TEL)==0)
2961
/* Invalid SDP, should not reach here */
2962
pj_assert(!"SDP should have been validated!");
2971
/* Schedule check for the need of re-INVITE/UPDATE after media update, cases:
2972
* - lock codec if remote answerer has given us more than one codecs
2973
* - update ICE default transport address if it has changed after ICE
2974
* connectivity check.
2976
void pjsua_call_schedule_reinvite_check(pjsua_call *call, unsigned delay_ms)
2980
/* Stop reinvite timer, if it is active */
2981
if (call->reinv_timer.id)
2982
pjsua_cancel_timer(&call->reinv_timer);
2985
delay.msec = delay_ms;
2986
pj_time_val_normalize(&delay);
2987
call->reinv_timer.id = PJ_TRUE;
2988
pjsua_schedule_timer(&call->reinv_timer, &delay);
2992
/* Check if lock codec is needed */
2993
static pj_bool_t check_lock_codec(pjsua_call *call)
2995
const pjmedia_sdp_session *local_sdp, *remote_sdp;
2996
pj_bool_t has_mult_fmt = PJ_FALSE;
3000
/* Check if lock codec is disabled */
3001
if (!pjsua_var.acc[call->acc_id].cfg.lock_codec)
3004
/* Check lock codec retry count */
3005
if (call->lock_codec.retry_cnt >= LOCK_CODEC_MAX_RETRY)
3008
/* Check if we are the answerer, we shouldn't need to lock codec */
3009
if (!call->inv->neg || !pjmedia_sdp_neg_was_answer_remote(call->inv->neg))
3012
/* Check if remote answerer has given us more than one codecs. */
3013
status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &local_sdp);
3014
if (status != PJ_SUCCESS)
3016
status = pjmedia_sdp_neg_get_active_remote(call->inv->neg, &remote_sdp);
3017
if (status != PJ_SUCCESS)
3020
for (i = 0; i < call->med_cnt && !has_mult_fmt; ++i) {
3021
pjsua_call_media *call_med = &call->media[i];
3022
const pjmedia_sdp_media *rem_m, *loc_m;
3023
unsigned codec_cnt = 0;
3026
/* Skip this if the media is inactive or error */
3027
if (call_med->state == PJSUA_CALL_MEDIA_NONE ||
3028
call_med->state == PJSUA_CALL_MEDIA_ERROR ||
3029
call_med->dir == PJMEDIA_DIR_NONE)
3034
/* Remote may answer with less media lines. */
3035
if (i >= remote_sdp->media_count)
3038
rem_m = remote_sdp->media[i];
3039
loc_m = local_sdp->media[i];
3041
/* Verify that media must be active. */
3042
pj_assert(loc_m->desc.port && rem_m->desc.port);
3044
/* Count the formats in the answer. */
3045
for (j=0; j<rem_m->desc.fmt_count && codec_cnt <= 1; ++j) {
3046
if (!is_non_av_fmt(rem_m, &rem_m->desc.fmt[j]) && ++codec_cnt > 1)
3047
has_mult_fmt = PJ_TRUE;
3051
/* Reset retry count when remote answer has one codec */
3053
call->lock_codec.retry_cnt = 0;
3055
return has_mult_fmt;
3058
/* Check if ICE setup is complete and if it needs to send reinvite */
3059
static pj_bool_t check_ice_complete(pjsua_call *call, pj_bool_t *need_reinv)
3061
pj_bool_t ice_need_reinv = PJ_FALSE;
3062
pj_bool_t ice_complete = PJ_TRUE;
3065
/* Check if ICE setup is complete and if it needs reinvite */
3066
for (i = 0; i < call->med_cnt; ++i) {
3067
pjsua_call_media *call_med = &call->media[i];
3068
pjmedia_transport_info tpinfo;
3069
pjmedia_ice_transport_info *ice_info;
3071
if (call_med->tp_st == PJSUA_MED_TP_NULL ||
3072
call_med->tp_st == PJSUA_MED_TP_DISABLED ||
3073
call_med->state == PJSUA_CALL_MEDIA_ERROR)
3078
pjmedia_transport_info_init(&tpinfo);
3079
pjmedia_transport_get_info(call_med->tp, &tpinfo);
3080
ice_info = (pjmedia_ice_transport_info*)
3081
pjmedia_transport_info_get_spc_info(
3082
&tpinfo, PJMEDIA_TRANSPORT_TYPE_ICE);
3084
/* Check if ICE is active */
3085
if (!ice_info || !ice_info->active)
3088
/* Check if ICE setup not completed yet */
3089
if (ice_info->sess_state < PJ_ICE_STRANS_STATE_RUNNING) {
3090
ice_complete = PJ_FALSE;
3094
/* Check if ICE needs to send reinvite */
3095
if (!ice_need_reinv &&
3096
ice_info->sess_state == PJ_ICE_STRANS_STATE_RUNNING &&
3097
ice_info->role == PJ_ICE_SESS_ROLE_CONTROLLING)
3099
pjsua_ice_config *cfg=&pjsua_var.acc[call->acc_id].cfg.ice_cfg;
3100
if ((cfg->ice_always_update && !call->reinv_ice_sent) ||
3101
pj_sockaddr_cmp(&tpinfo.sock_info.rtp_addr_name,
3102
&call_med->rtp_addr))
3104
ice_need_reinv = PJ_TRUE;
3109
if (ice_complete && need_reinv)
3110
*need_reinv = ice_need_reinv;
3112
return ice_complete;
3115
/* Check and send reinvite for lock codec and ICE update */
3116
static pj_status_t process_pending_reinvite(pjsua_call *call)
3118
const pj_str_t ST_UPDATE = {"UPDATE", 6};
3119
pj_pool_t *pool = call->inv->pool_prov;
3120
pjsip_inv_session *inv = call->inv;
3121
pj_bool_t ice_need_reinv;
3122
pj_bool_t ice_completed;
3123
pj_bool_t need_lock_codec;
3124
pj_bool_t rem_can_update;
3125
pjmedia_sdp_session *new_offer;
3126
pjsip_tx_data *tdata;
3130
/* Verify if another SDP negotiation is in progress, e.g: session timer
3131
* or another re-INVITE.
3133
if (inv==NULL || inv->neg==NULL ||
3134
pjmedia_sdp_neg_get_state(inv->neg)!=PJMEDIA_SDP_NEG_STATE_DONE)
3136
return PJMEDIA_SDPNEG_EINSTATE;
3139
/* Don't do this if call is disconnecting! */
3140
if (inv->state > PJSIP_INV_STATE_CONFIRMED || inv->cause >= 200)
3142
return PJ_EINVALIDOP;
3145
/* Delay this when the SDP negotiation done in call state EARLY and
3146
* remote does not support UPDATE method.
3148
if (inv->state == PJSIP_INV_STATE_EARLY &&
3149
pjsip_dlg_remote_has_cap(inv->dlg, PJSIP_H_ALLOW, NULL, &ST_UPDATE)!=
3150
PJSIP_DIALOG_CAP_SUPPORTED)
3152
call->reinv_pending = PJ_TRUE;
3156
/* Check if ICE setup is complete and if it needs reinvite */
3157
ice_completed = check_ice_complete(call, &ice_need_reinv);
3161
/* Check if we need to lock codec */
3162
need_lock_codec = check_lock_codec(call);
3164
/* Check if reinvite is really needed */
3165
if (!need_lock_codec && !ice_need_reinv)
3169
/* Okay! So we need to send re-INVITE/UPDATE */
3171
/* Check if remote support UPDATE */
3172
rem_can_update = pjsip_dlg_remote_has_cap(inv->dlg, PJSIP_H_ALLOW, NULL,
3174
PJSIP_DIALOG_CAP_SUPPORTED;
3178
const char *ST_ICE_UPDATE = "ICE transport address after "
3180
const char *ST_LOCK_CODEC = "media session to use only one codec";
3181
PJ_LOG(4,(THIS_FILE, "Call %d sending %s for updating %s%s%s",
3183
(rem_can_update? "UPDATE" : "re-INVITE"),
3184
(ice_need_reinv? ST_ICE_UPDATE : ST_LOCK_CODEC),
3185
(ice_need_reinv && need_lock_codec? " and " : ""),
3186
(ice_need_reinv && need_lock_codec? ST_LOCK_CODEC : "")
3190
/* Generate SDP re-offer */
3191
status = pjsua_media_channel_create_sdp(call->index, pool, NULL,
3193
if (status != PJ_SUCCESS) {
3194
pjsua_perror(THIS_FILE, "Unable to create local SDP", status);
3198
/* Update the new offer so it contains only a codec. Note that
3199
* SDP nego has removed unmatched codecs from the offer and the codec
3200
* order in the offer has been matched to the answer, so we'll override
3201
* the codecs in the just generated SDP with the ones from the active
3202
* local SDP and leave just one codec for the next SDP re-offer.
3204
if (need_lock_codec) {
3205
const pjmedia_sdp_session *ref_sdp;
3207
/* Get local active SDP as reference */
3208
status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &ref_sdp);
3209
if (status != PJ_SUCCESS)
3212
/* Verify media count. Note that remote may add/remove media line
3213
* in the answer. When answer has less media, it must have been
3214
* handled by pjsua_media_channel_update() as disabled media.
3215
* When answer has more media, it must have been ignored (treated
3216
* as non-exist) anywhere. Local media count should not be updated
3217
* at this point, as modifying media count operation (i.e: reinvite,
3218
* update, vid_set_strm) is currently blocking, protected with
3219
* dialog mutex, and eventually reset SDP nego state to LOCAL OFFER.
3221
if (call->med_cnt != ref_sdp->media_count ||
3222
ref_sdp->media_count != new_offer->media_count)
3224
/* Anyway, just in case, let's just return error */
3225
return PJMEDIA_SDPNEG_EINSTATE;
3228
for (i = 0; i < call->med_cnt; ++i) {
3229
unsigned j, codec_cnt = 0;
3230
const pjmedia_sdp_media *ref_m = ref_sdp->media[i];
3231
pjmedia_sdp_media *m = new_offer->media[i];
3232
pjsua_call_media *call_med = &call->media[i];
3234
/* Verify if media is deactivated */
3235
if (call_med->state == PJSUA_CALL_MEDIA_NONE ||
3236
call_med->state == PJSUA_CALL_MEDIA_ERROR ||
3237
call_med->dir == PJMEDIA_DIR_NONE)
3243
m->desc.fmt_count = 0;
3244
pjmedia_sdp_attr_remove_all(&m->attr_count, m->attr, "rtpmap");
3245
pjmedia_sdp_attr_remove_all(&m->attr_count, m->attr, "fmtp");
3247
/* Copy only the first format + any non-AV formats from
3248
* the active local SDP.
3250
for (j = 0; j < ref_m->desc.fmt_count; ++j) {
3251
const pj_str_t *fmt = &ref_m->desc.fmt[j];
3253
if (is_non_av_fmt(ref_m, fmt) || (++codec_cnt == 1)) {
3254
pjmedia_sdp_attr *a;
3256
m->desc.fmt[m->desc.fmt_count++] = *fmt;
3257
a = pjmedia_sdp_attr_find2(ref_m->attr_count, ref_m->attr,
3259
if (a) pjmedia_sdp_attr_add(&m->attr_count, m->attr, a);
3260
a = pjmedia_sdp_attr_find2(ref_m->attr_count, ref_m->attr,
3262
if (a) pjmedia_sdp_attr_add(&m->attr_count, m->attr, a);
3268
/* Put back original direction and "c=0.0.0.0" line */
3270
const pjmedia_sdp_session *cur_sdp;
3272
/* Get local active SDP */
3273
status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &cur_sdp);
3274
if (status != PJ_SUCCESS)
3277
/* Make sure media count has not been changed */
3278
if (call->med_cnt != cur_sdp->media_count)
3279
return PJMEDIA_SDPNEG_EINSTATE;
3281
for (i = 0; i < call->med_cnt; ++i) {
3282
const pjmedia_sdp_media *m = cur_sdp->media[i];
3283
pjmedia_sdp_media *new_m = new_offer->media[i];
3284
pjsua_call_media *call_med = &call->media[i];
3285
pjmedia_sdp_attr *a = NULL;
3287
/* Update direction to the current dir */
3288
pjmedia_sdp_media_remove_all_attr(new_m, "sendrecv");
3289
pjmedia_sdp_media_remove_all_attr(new_m, "sendonly");
3290
pjmedia_sdp_media_remove_all_attr(new_m, "recvonly");
3291
pjmedia_sdp_media_remove_all_attr(new_m, "inactive");
3293
if (call_med->dir == PJMEDIA_DIR_ENCODING_DECODING) {
3294
a = pjmedia_sdp_attr_create(pool, "sendrecv", NULL);
3295
} else if (call_med->dir == PJMEDIA_DIR_ENCODING) {
3296
a = pjmedia_sdp_attr_create(pool, "sendonly", NULL);
3297
} else if (call_med->dir == PJMEDIA_DIR_DECODING) {
3298
a = pjmedia_sdp_attr_create(pool, "recvonly", NULL);
3300
const pjmedia_sdp_conn *conn;
3301
a = pjmedia_sdp_attr_create(pool, "inactive", NULL);
3303
/* Also check if the original c= line address is zero */
3306
conn = cur_sdp->conn;
3307
if (pj_strcmp2(&conn->addr, "0.0.0.0")==0 ||
3308
pj_strcmp2(&conn->addr, "0")==0)
3311
new_m->conn = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_conn);
3314
if (pj_strcmp2(&new_m->conn->addr, "0.0.0.0")) {
3315
new_m->conn->net_type = pj_str("IN");
3316
new_m->conn->addr_type = pj_str("IP4");
3317
new_m->conn->addr = pj_str("0.0.0.0");
3323
pjmedia_sdp_media_add_attr(new_m, a);
3328
if (rem_can_update) {
3329
status = pjsip_inv_update(inv, NULL, new_offer, &tdata);
3331
status = pjsip_inv_reinvite(inv, NULL, new_offer, &tdata);
3334
if (status==PJ_EINVALIDOP &&
3335
++call->lock_codec.retry_cnt < LOCK_CODEC_MAX_RETRY)
3337
/* Ups, let's reschedule again */
3338
pjsua_call_schedule_reinvite_check(call, LOCK_CODEC_RETRY_INTERVAL);
3340
} else if (status != PJ_SUCCESS) {
3341
pjsua_perror(THIS_FILE, "Error creating UPDATE/re-INVITE",
3346
/* Send the UPDATE/re-INVITE request */
3347
status = pjsip_inv_send_msg(inv, tdata);
3348
if (status != PJ_SUCCESS) {
3349
pjsua_perror(THIS_FILE, "Error sending UPDATE/re-INVITE",
3356
call->reinv_ice_sent = PJ_TRUE;
3357
if (need_lock_codec)
3358
++call->lock_codec.retry_cnt;
3365
* This callback receives notification from invite session when the
3366
* session state has changed.
3368
static void pjsua_call_on_state_changed(pjsip_inv_session *inv,
3373
pj_log_push_indent();
3375
call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id];
3378
pj_log_pop_indent();
3383
/* Get call times */
3384
switch (inv->state) {
3385
case PJSIP_INV_STATE_EARLY:
3386
case PJSIP_INV_STATE_CONNECTING:
3387
if (call->res_time.sec == 0)
3388
pj_gettimeofday(&call->res_time);
3389
call->last_code = (pjsip_status_code)
3390
e->body.tsx_state.tsx->status_code;
3391
pj_strncpy(&call->last_text,
3392
&e->body.tsx_state.tsx->status_text,
3393
sizeof(call->last_text_buf_));
3395
case PJSIP_INV_STATE_CONFIRMED:
3396
pj_gettimeofday(&call->conn_time);
3398
/* See if auto reinvite was pended as media update was done in the
3399
* EARLY state and remote does not support UPDATE.
3401
if (call->reinv_pending) {
3402
call->reinv_pending = PJ_FALSE;
3403
pjsua_call_schedule_reinvite_check(call, 0);
3406
case PJSIP_INV_STATE_DISCONNECTED:
3407
pj_gettimeofday(&call->dis_time);
3408
if (call->res_time.sec == 0)
3409
pj_gettimeofday(&call->res_time);
3410
if (e->type == PJSIP_EVENT_TSX_STATE &&
3411
e->body.tsx_state.tsx->status_code > call->last_code)
3413
call->last_code = (pjsip_status_code)
3414
e->body.tsx_state.tsx->status_code;
3415
pj_strncpy(&call->last_text,
3416
&e->body.tsx_state.tsx->status_text,
3417
sizeof(call->last_text_buf_));
3419
call->last_code = PJSIP_SC_REQUEST_TERMINATED;
3420
pj_strncpy(&call->last_text,
3421
pjsip_get_status_text(call->last_code),
3422
sizeof(call->last_text_buf_));
3425
/* Stop reinvite timer, if it is active */
3426
if (call->reinv_timer.id) {
3427
pjsua_cancel_timer(&call->reinv_timer);
3428
call->reinv_timer.id = PJ_FALSE;
3432
call->last_code = (pjsip_status_code)
3433
e->body.tsx_state.tsx->status_code;
3434
pj_strncpy(&call->last_text,
3435
&e->body.tsx_state.tsx->status_text,
3436
sizeof(call->last_text_buf_));
3440
/* If this is an outgoing INVITE that was created because of
3441
* REFER/transfer, send NOTIFY to transferer.
3443
if (call->xfer_sub && e->type==PJSIP_EVENT_TSX_STATE) {
3445
pjsip_evsub_state ev_state = PJSIP_EVSUB_STATE_ACTIVE;
3448
switch (call->inv->state) {
3449
case PJSIP_INV_STATE_NULL:
3450
case PJSIP_INV_STATE_CALLING:
3454
case PJSIP_INV_STATE_EARLY:
3455
case PJSIP_INV_STATE_CONNECTING:
3456
st_code = e->body.tsx_state.tsx->status_code;
3457
if (call->inv->state == PJSIP_INV_STATE_CONNECTING)
3458
ev_state = PJSIP_EVSUB_STATE_TERMINATED;
3460
ev_state = PJSIP_EVSUB_STATE_ACTIVE;
3463
case PJSIP_INV_STATE_CONFIRMED:
3465
/* We don't need this, as we've terminated the subscription in
3468
/* When state is confirmed, send the final 200/OK and terminate
3471
st_code = e->body.tsx_state.tsx->status_code;
3472
ev_state = PJSIP_EVSUB_STATE_TERMINATED;
3476
case PJSIP_INV_STATE_DISCONNECTED:
3477
st_code = e->body.tsx_state.tsx->status_code;
3478
ev_state = PJSIP_EVSUB_STATE_TERMINATED;
3481
case PJSIP_INV_STATE_INCOMING:
3482
/* Nothing to do. Just to keep gcc from complaining about
3488
if (st_code != -1) {
3489
pjsip_tx_data *tdata;
3492
status = pjsip_xfer_notify( call->xfer_sub,
3495
if (status != PJ_SUCCESS) {
3496
pjsua_perror(THIS_FILE, "Unable to create NOTIFY", status);
3498
status = pjsip_xfer_send_request(call->xfer_sub, tdata);
3499
if (status != PJ_SUCCESS) {
3500
pjsua_perror(THIS_FILE, "Unable to send NOTIFY", status);
3506
/* Ticket #1627: Invoke on_call_tsx_state() when call is disconnected. */
3507
if (inv->state == PJSIP_INV_STATE_DISCONNECTED &&
3508
e->type == PJSIP_EVENT_TSX_STATE &&
3510
pjsua_var.ua_cfg.cb.on_call_tsx_state)
3512
(*pjsua_var.ua_cfg.cb.on_call_tsx_state)(call->index,
3513
e->body.tsx_state.tsx, e);
3516
if (pjsua_var.ua_cfg.cb.on_call_state)
3517
(*pjsua_var.ua_cfg.cb.on_call_state)(call->index, e);
3519
/* call->inv may be NULL now */
3521
/* Destroy media session when invite session is disconnected. */
3522
if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
3526
pjsua_media_channel_deinit(call->index);
3531
pj_assert(pjsua_var.call_cnt > 0);
3532
--pjsua_var.call_cnt;
3535
reset_call(call->index);
3537
pjsua_check_snd_dev_idle();
3541
pj_log_pop_indent();
3545
* This callback is called by invite session framework when UAC session
3548
static void pjsua_call_on_forked( pjsip_inv_session *inv,
3554
PJ_TODO(HANDLE_FORKED_DIALOG);
3559
* Callback from UA layer when forked dialog response is received.
3561
pjsip_dialog* on_dlg_forked(pjsip_dialog *dlg, pjsip_rx_data *res)
3563
if (dlg->uac_has_2xx &&
3564
res->msg_info.cseq->method.id == PJSIP_INVITE_METHOD &&
3565
pjsip_rdata_get_tsx(res) == NULL &&
3566
res->msg_info.msg->line.status.code/100 == 2)
3568
pjsip_dialog *forked_dlg;
3572
/* Create forked dialog */
3573
status = pjsip_dlg_fork(dlg, res, &forked_dlg);
3574
if (status != PJ_SUCCESS)
3577
pjsip_dlg_inc_lock(forked_dlg);
3579
/* Disconnect the call */
3580
status = pjsip_dlg_create_request(forked_dlg, &pjsip_bye_method,
3582
if (status == PJ_SUCCESS) {
3583
status = pjsip_dlg_send_request(forked_dlg, bye, -1, NULL);
3586
pjsip_dlg_dec_lock(forked_dlg);
3588
if (status != PJ_SUCCESS) {
3600
* Disconnect call upon error.
3602
static void call_disconnect( pjsip_inv_session *inv,
3606
pjsip_tx_data *tdata;
3609
call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id];
3611
status = pjsip_inv_end_session(inv, code, NULL, &tdata);
3612
if (status != PJ_SUCCESS)
3615
/* Add SDP in 488 status */
3616
#if DISABLED_FOR_TICKET_1185
3617
if (call && call->tp && tdata->msg->type==PJSIP_RESPONSE_MSG &&
3618
code==PJSIP_SC_NOT_ACCEPTABLE_HERE)
3620
pjmedia_sdp_session *local_sdp;
3621
pjmedia_transport_info ti;
3623
pjmedia_transport_info_init(&ti);
3624
pjmedia_transport_get_info(call->med_tp, &ti);
3625
status = pjmedia_endpt_create_sdp(pjsua_var.med_endpt, tdata->pool,
3626
1, &ti.sock_info, &local_sdp);
3627
if (status == PJ_SUCCESS) {
3628
pjsip_create_sdp_body(tdata->pool, local_sdp,
3634
pjsip_inv_send_msg(inv, tdata);
3638
* Callback to be called when SDP offer/answer negotiation has just completed
3639
* in the session. This function will start/update media if negotiation
3642
static void pjsua_call_on_media_update(pjsip_inv_session *inv,
3646
const pjmedia_sdp_session *local_sdp;
3647
const pjmedia_sdp_session *remote_sdp;
3648
//const pj_str_t st_update = {"UPDATE", 6};
3650
pj_log_push_indent();
3652
call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id];
3654
if (status != PJ_SUCCESS) {
3656
pjsua_perror(THIS_FILE, "SDP negotiation has failed", status);
3658
/* Clean up provisional media */
3659
pjsua_media_prov_clean_up(call->index);
3661
/* Do not deinitialize media since this may be a re-INVITE or
3662
* UPDATE (which in this case the media should not get affected
3663
* by the failed re-INVITE/UPDATE). The media will be shutdown
3664
* when call is disconnected anyway.
3666
/* Stop/destroy media, if any */
3667
/*pjsua_media_channel_deinit(call->index);*/
3669
/* Disconnect call if we're not in the middle of initializing an
3670
* UAS dialog and if this is not a re-INVITE
3672
if (inv->state != PJSIP_INV_STATE_NULL &&
3673
inv->state != PJSIP_INV_STATE_CONFIRMED)
3675
call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE);
3682
/* Get local and remote SDP */
3683
status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &local_sdp);
3684
if (status != PJ_SUCCESS) {
3685
pjsua_perror(THIS_FILE,
3686
"Unable to retrieve currently active local SDP",
3688
//call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE);
3692
status = pjmedia_sdp_neg_get_active_remote(call->inv->neg, &remote_sdp);
3693
if (status != PJ_SUCCESS) {
3694
pjsua_perror(THIS_FILE,
3695
"Unable to retrieve currently active remote SDP",
3697
//call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE);
3701
/* Update remote's NAT type */
3702
if (pjsua_var.ua_cfg.nat_type_in_sdp) {
3703
update_remote_nat_type(call, remote_sdp);
3706
/* Update media channel with the new SDP */
3707
status = pjsua_media_channel_update(call->index, local_sdp, remote_sdp);
3708
if (status != PJ_SUCCESS) {
3709
pjsua_perror(THIS_FILE, "Unable to create media session",
3711
call_disconnect(inv, PJSIP_SC_NOT_ACCEPTABLE_HERE);
3712
/* No need to deinitialize; media will be shutdown when call
3713
* state is disconnected anyway.
3715
/*pjsua_media_channel_deinit(call->index);*/
3719
/* Ticket #476: make sure only one codec is specified in the answer. */
3720
pjsua_call_schedule_reinvite_check(call, 0);
3722
/* Call application callback, if any */
3723
if (pjsua_var.ua_cfg.cb.on_call_media_state)
3724
pjsua_var.ua_cfg.cb.on_call_media_state(call->index);
3727
pj_log_pop_indent();
3731
/* Modify SDP for call hold. */
3732
static pj_status_t modify_sdp_of_call_hold(pjsua_call *call,
3734
pjmedia_sdp_session *sdp)
3738
/* Call-hold is done by set the media direction to 'sendonly'
3739
* (PJMEDIA_DIR_ENCODING), except when current media direction is
3740
* 'inactive' (PJMEDIA_DIR_NONE).
3741
* (See RFC 3264 Section 8.4 and RFC 4317 Section 3.1)
3743
/* http://trac.pjsip.org/repos/ticket/880
3744
if (call->dir != PJMEDIA_DIR_ENCODING) {
3746
/* https://trac.pjsip.org/repos/ticket/1142:
3747
* configuration to use c=0.0.0.0 for call hold.
3750
for (mi=0; mi<sdp->media_count; ++mi) {
3751
pjmedia_sdp_media *m = sdp->media[mi];
3753
if (call->call_hold_type == PJSUA_CALL_HOLD_TYPE_RFC2543) {
3754
pjmedia_sdp_conn *conn;
3755
pjmedia_sdp_attr *attr;
3757
/* Get SDP media connection line */
3762
/* Modify address */
3763
conn->addr = pj_str("0.0.0.0");
3765
/* Remove existing directions attributes */
3766
pjmedia_sdp_media_remove_all_attr(m, "sendrecv");
3767
pjmedia_sdp_media_remove_all_attr(m, "sendonly");
3768
pjmedia_sdp_media_remove_all_attr(m, "recvonly");
3769
pjmedia_sdp_media_remove_all_attr(m, "inactive");
3771
/* Add inactive attribute */
3772
attr = pjmedia_sdp_attr_create(pool, "inactive", NULL);
3773
pjmedia_sdp_media_add_attr(m, attr);
3777
pjmedia_sdp_attr *attr;
3779
/* Remove existing directions attributes */
3780
pjmedia_sdp_media_remove_all_attr(m, "sendrecv");
3781
pjmedia_sdp_media_remove_all_attr(m, "sendonly");
3782
pjmedia_sdp_media_remove_all_attr(m, "recvonly");
3783
pjmedia_sdp_media_remove_all_attr(m, "inactive");
3785
if (call->media[mi].dir & PJMEDIA_DIR_ENCODING) {
3786
/* Add sendonly attribute */
3787
attr = pjmedia_sdp_attr_create(pool, "sendonly", NULL);
3788
pjmedia_sdp_media_add_attr(m, attr);
3790
/* Add inactive attribute */
3791
attr = pjmedia_sdp_attr_create(pool, "inactive", NULL);
3792
pjmedia_sdp_media_add_attr(m, attr);
3800
/* Create SDP for call hold. */
3801
static pj_status_t create_sdp_of_call_hold(pjsua_call *call,
3802
pjmedia_sdp_session **p_sdp)
3806
pjmedia_sdp_session *sdp;
3808
/* Use call's provisional pool */
3809
pool = call->inv->pool_prov;
3811
/* Create new offer */
3812
status = pjsua_media_channel_create_sdp(call->index, pool, NULL, &sdp,
3814
if (status != PJ_SUCCESS) {
3815
pjsua_perror(THIS_FILE, "Unable to create local SDP", status);
3819
status = modify_sdp_of_call_hold(call, pool, sdp);
3820
if (status != PJ_SUCCESS)
3829
* Called when session received new offer.
3831
static void pjsua_call_on_rx_offer(pjsip_inv_session *inv,
3832
const pjmedia_sdp_session *offer)
3835
pjmedia_sdp_session *answer;
3839
call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id];
3841
/* Supply candidate answer */
3842
PJ_LOG(4,(THIS_FILE, "Call %d: received updated media offer",
3844
pj_log_push_indent();
3846
if (pjsua_var.ua_cfg.cb.on_call_rx_offer) {
3847
pjsip_status_code code = PJSIP_SC_OK;
3848
pjsua_call_setting opt = call->opt;
3850
(*pjsua_var.ua_cfg.cb.on_call_rx_offer)(call->index, offer, NULL,
3853
if (code != PJSIP_SC_OK) {
3854
PJ_LOG(4,(THIS_FILE, "Rejecting updated media offer on call %d",
3862
/* Re-init media for the new remote offer before creating SDP */
3863
status = apply_call_setting(call, &call->opt, offer);
3864
if (status != PJ_SUCCESS)
3867
status = pjsua_media_channel_create_sdp(call->index,
3868
call->inv->pool_prov,
3869
offer, &answer, NULL);
3870
if (status != PJ_SUCCESS) {
3871
pjsua_perror(THIS_FILE, "Unable to create local SDP", status);
3875
/* Validate media count in the generated answer */
3876
pj_assert(answer->media_count == offer->media_count);
3878
/* Check if offer's conn address is zero */
3879
for (i = 0; i < answer->media_count; ++i) {
3880
pjmedia_sdp_conn *conn;
3882
conn = offer->media[i]->conn;
3886
if (pj_strcmp2(&conn->addr, "0.0.0.0")==0 ||
3887
pj_strcmp2(&conn->addr, "0")==0)
3889
pjmedia_sdp_conn *a_conn = answer->media[i]->conn;
3891
/* Modify answer address */
3893
a_conn->addr = pj_str("0.0.0.0");
3894
} else if (answer->conn == NULL ||
3895
pj_strcmp2(&answer->conn->addr, "0.0.0.0") != 0)
3897
a_conn = PJ_POOL_ZALLOC_T(call->inv->pool_prov,
3899
a_conn->net_type = pj_str("IN");
3900
a_conn->addr_type = pj_str("IP4");
3901
a_conn->addr = pj_str("0.0.0.0");
3902
answer->media[i]->conn = a_conn;
3907
/* Check if call is on-hold */
3908
if (call->local_hold) {
3909
modify_sdp_of_call_hold(call, call->inv->pool_prov, answer);
3912
status = pjsip_inv_set_sdp_answer(call->inv, answer);
3913
if (status != PJ_SUCCESS) {
3914
pjsua_perror(THIS_FILE, "Unable to set answer", status);
3919
pj_log_pop_indent();
3924
* Called to generate new offer.
3926
static void pjsua_call_on_create_offer(pjsip_inv_session *inv,
3927
pjmedia_sdp_session **offer)
3932
pj_log_push_indent();
3934
call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id];
3936
/* See if we've put call on hold. */
3937
if (call->local_hold) {
3938
PJ_LOG(4,(THIS_FILE,
3939
"Call %d: call is on-hold locally, creating call-hold SDP ",
3941
status = create_sdp_of_call_hold( call, offer );
3943
PJ_LOG(4,(THIS_FILE, "Call %d: asked to send a new offer",
3946
status = pjsua_media_channel_create_sdp(call->index,
3947
call->inv->pool_prov,
3951
if (status != PJ_SUCCESS) {
3952
pjsua_perror(THIS_FILE, "Unable to create local SDP", status);
3957
pj_log_pop_indent();
3962
* Callback called by event framework when the xfer subscription state
3965
static void xfer_client_on_evsub_state( pjsip_evsub *sub, pjsip_event *event)
3968
PJ_UNUSED_ARG(event);
3970
pj_log_push_indent();
3973
* When subscription is accepted (got 200/OK to REFER), check if
3974
* subscription suppressed.
3976
if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_ACCEPTED) {
3978
pjsip_rx_data *rdata;
3979
pjsip_generic_string_hdr *refer_sub;
3980
const pj_str_t REFER_SUB = { "Refer-Sub", 9 };
3983
call = (pjsua_call*) pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id);
3985
/* Must be receipt of response message */
3986
pj_assert(event->type == PJSIP_EVENT_TSX_STATE &&
3987
event->body.tsx_state.type == PJSIP_EVENT_RX_MSG);
3988
rdata = event->body.tsx_state.src.rdata;
3990
/* Find Refer-Sub header */
3991
refer_sub = (pjsip_generic_string_hdr*)
3992
pjsip_msg_find_hdr_by_name(rdata->msg_info.msg,
3995
/* Check if subscription is suppressed */
3996
if (refer_sub && pj_stricmp2(&refer_sub->hvalue, "false")==0) {
3997
/* Since no subscription is desired, assume that call has been
3998
* transfered successfully.
4000
if (call && pjsua_var.ua_cfg.cb.on_call_transfer_status) {
4001
const pj_str_t ACCEPTED = { "Accepted", 8 };
4002
pj_bool_t cont = PJ_FALSE;
4003
(*pjsua_var.ua_cfg.cb.on_call_transfer_status)(call->index,
4010
/* Yes, subscription is suppressed.
4011
* Terminate our subscription now.
4013
PJ_LOG(4,(THIS_FILE, "Xfer subscription suppressed, terminating "
4014
"event subcription..."));
4015
pjsip_evsub_terminate(sub, PJ_TRUE);
4018
/* Notify application about call transfer progress.
4019
* Initially notify with 100/Accepted status.
4021
if (call && pjsua_var.ua_cfg.cb.on_call_transfer_status) {
4022
const pj_str_t ACCEPTED = { "Accepted", 8 };
4023
pj_bool_t cont = PJ_FALSE;
4024
(*pjsua_var.ua_cfg.cb.on_call_transfer_status)(call->index,
4033
* On incoming NOTIFY, notify application about call transfer progress.
4035
else if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_ACTIVE ||
4036
pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED)
4040
pjsip_msg_body *body;
4041
pjsip_status_line status_line;
4046
call = (pjsua_call*) pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id);
4048
/* When subscription is terminated, clear the xfer_sub member of
4051
if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) {
4052
pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, NULL);
4053
PJ_LOG(4,(THIS_FILE, "Xfer client subscription terminated"));
4057
if (!call || !event || !pjsua_var.ua_cfg.cb.on_call_transfer_status) {
4058
/* Application is not interested with call progress status */
4062
/* This better be a NOTIFY request */
4063
if (event->type == PJSIP_EVENT_TSX_STATE &&
4064
event->body.tsx_state.type == PJSIP_EVENT_RX_MSG)
4066
pjsip_rx_data *rdata;
4068
rdata = event->body.tsx_state.src.rdata;
4070
/* Check if there's body */
4071
msg = rdata->msg_info.msg;
4074
PJ_LOG(2,(THIS_FILE,
4075
"Warning: received NOTIFY without message body"));
4079
/* Check for appropriate content */
4080
if (pj_stricmp2(&body->content_type.type, "message") != 0 ||
4081
pj_stricmp2(&body->content_type.subtype, "sipfrag") != 0)
4083
PJ_LOG(2,(THIS_FILE,
4084
"Warning: received NOTIFY with non message/sipfrag "
4089
/* Try to parse the content */
4090
status = pjsip_parse_status_line((char*)body->data, body->len,
4092
if (status != PJ_SUCCESS) {
4093
PJ_LOG(2,(THIS_FILE,
4094
"Warning: received NOTIFY with invalid "
4095
"message/sipfrag content"));
4100
status_line.code = 500;
4101
status_line.reason = *pjsip_get_status_text(500);
4104
/* Notify application */
4105
is_last = (pjsip_evsub_get_state(sub)==PJSIP_EVSUB_STATE_TERMINATED);
4107
(*pjsua_var.ua_cfg.cb.on_call_transfer_status)(call->index,
4109
&status_line.reason,
4113
pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, NULL);
4116
/* If the call transfer has completed but the subscription is
4117
* not terminated, terminate it now.
4119
if (status_line.code/100 == 2 && !is_last) {
4120
pjsip_tx_data *tdata;
4122
status = pjsip_evsub_initiate(sub, &pjsip_subscribe_method,
4124
if (status == PJ_SUCCESS)
4125
status = pjsip_evsub_send_request(sub, tdata);
4130
pj_log_pop_indent();
4135
* Callback called by event framework when the xfer subscription state
4138
static void xfer_server_on_evsub_state( pjsip_evsub *sub, pjsip_event *event)
4140
PJ_UNUSED_ARG(event);
4142
pj_log_push_indent();
4145
* When subscription is terminated, clear the xfer_sub member of
4148
if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) {
4151
call = (pjsua_call*) pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id);
4155
pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, NULL);
4156
call->xfer_sub = NULL;
4158
PJ_LOG(4,(THIS_FILE, "Xfer server subscription terminated"));
4162
pj_log_pop_indent();
4167
* Follow transfer (REFER) request.
4169
static void on_call_transfered( pjsip_inv_session *inv,
4170
pjsip_rx_data *rdata )
4173
pjsip_tx_data *tdata;
4174
pjsua_call *existing_call;
4176
const pj_str_t str_refer_to = { "Refer-To", 8};
4177
const pj_str_t str_refer_sub = { "Refer-Sub", 9 };
4178
const pj_str_t str_ref_by = { "Referred-By", 11 };
4179
pjsip_generic_string_hdr *refer_to;
4180
pjsip_generic_string_hdr *refer_sub;
4181
pjsip_hdr *ref_by_hdr;
4182
pj_bool_t no_refer_sub = PJ_FALSE;
4184
pjsua_msg_data msg_data;
4186
pjsip_status_code code;
4188
pjsua_call_setting call_opt;
4190
pj_log_push_indent();
4192
existing_call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id];
4194
/* Find the Refer-To header */
4195
refer_to = (pjsip_generic_string_hdr*)
4196
pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_refer_to, NULL);
4198
if (refer_to == NULL) {
4200
* No Refer-To header!
4202
PJ_LOG(4,(THIS_FILE, "Received REFER without Refer-To header!"));
4203
pjsip_dlg_respond( inv->dlg, rdata, 400, NULL, NULL, NULL);
4207
/* Find optional Refer-Sub header */
4208
refer_sub = (pjsip_generic_string_hdr*)
4209
pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_refer_sub, NULL);
4212
if (!pj_strnicmp2(&refer_sub->hvalue, "true", 4)==0)
4213
no_refer_sub = PJ_TRUE;
4216
/* Find optional Referred-By header (to be copied onto outgoing INVITE
4219
ref_by_hdr = (pjsip_hdr*)
4220
pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_ref_by,
4223
/* Notify callback */
4224
code = PJSIP_SC_ACCEPTED;
4225
if (pjsua_var.ua_cfg.cb.on_call_transfer_request) {
4226
(*pjsua_var.ua_cfg.cb.on_call_transfer_request)(existing_call->index,
4231
call_opt = existing_call->opt;
4232
if (pjsua_var.ua_cfg.cb.on_call_transfer_request2) {
4233
(*pjsua_var.ua_cfg.cb.on_call_transfer_request2)(existing_call->index,
4240
code = PJSIP_SC_ACCEPTED;
4242
/* Application rejects call transfer request */
4243
pjsip_dlg_respond( inv->dlg, rdata, code, NULL, NULL, NULL);
4247
PJ_LOG(3,(THIS_FILE, "Call to %.*s is being transfered to %.*s",
4248
(int)inv->dlg->remote.info_str.slen,
4249
inv->dlg->remote.info_str.ptr,
4250
(int)refer_to->hvalue.slen,
4251
refer_to->hvalue.ptr));
4255
* Always answer with 2xx.
4257
pjsip_tx_data *tdata;
4258
const pj_str_t str_false = { "false", 5};
4261
status = pjsip_dlg_create_response(inv->dlg, rdata, code, NULL,
4263
if (status != PJ_SUCCESS) {
4264
pjsua_perror(THIS_FILE, "Unable to create 2xx response to REFER",
4269
/* Add Refer-Sub header */
4271
pjsip_generic_string_hdr_create(tdata->pool, &str_refer_sub,
4273
pjsip_msg_add_hdr(tdata->msg, hdr);
4277
status = pjsip_dlg_send_response(inv->dlg, pjsip_rdata_get_tsx(rdata),
4279
if (status != PJ_SUCCESS) {
4280
pjsua_perror(THIS_FILE, "Unable to create 2xx response to REFER",
4285
/* Don't have subscription */
4289
struct pjsip_evsub_user xfer_cb;
4293
pj_bzero(&xfer_cb, sizeof(xfer_cb));
4294
xfer_cb.on_evsub_state = &xfer_server_on_evsub_state;
4296
/* Init additional header list to be sent with REFER response */
4297
pj_list_init(&hdr_list);
4299
/* Create transferee event subscription */
4300
status = pjsip_xfer_create_uas( inv->dlg, &xfer_cb, rdata, &sub);
4301
if (status != PJ_SUCCESS) {
4302
pjsua_perror(THIS_FILE, "Unable to create xfer uas", status);
4303
pjsip_dlg_respond( inv->dlg, rdata, 500, NULL, NULL, NULL);
4307
/* If there's Refer-Sub header and the value is "true", send back
4308
* Refer-Sub in the response with value "true" too.
4311
const pj_str_t str_true = { "true", 4 };
4315
pjsip_generic_string_hdr_create(inv->dlg->pool,
4318
pj_list_push_back(&hdr_list, hdr);
4322
/* Accept the REFER request, send 2xx. */
4323
pjsip_xfer_accept(sub, rdata, code, &hdr_list);
4325
/* Create initial NOTIFY request */
4326
status = pjsip_xfer_notify( sub, PJSIP_EVSUB_STATE_ACTIVE,
4328
if (status != PJ_SUCCESS) {
4329
pjsua_perror(THIS_FILE, "Unable to create NOTIFY to REFER",
4334
/* Send initial NOTIFY request */
4335
status = pjsip_xfer_send_request( sub, tdata);
4336
if (status != PJ_SUCCESS) {
4337
pjsua_perror(THIS_FILE, "Unable to send NOTIFY to REFER", status);
4342
/* We're cheating here.
4343
* We need to get a null terminated string from a pj_str_t.
4344
* So grab the pointer from the hvalue and NULL terminate it, knowing
4345
* that the NULL position will be occupied by a newline.
4347
uri = refer_to->hvalue.ptr;
4348
uri[refer_to->hvalue.slen] = '\0';
4351
pjsua_msg_data_init(&msg_data);
4353
/* If Referred-By header is present in the REFER request, copy this
4354
* to the outgoing INVITE request.
4356
if (ref_by_hdr != NULL) {
4357
pjsip_hdr *dup = (pjsip_hdr*)
4358
pjsip_hdr_clone(rdata->tp_info.pool, ref_by_hdr);
4359
pj_list_push_back(&msg_data.hdr_list, dup);
4362
/* Now make the outgoing call. */
4364
status = pjsua_call_make_call(existing_call->acc_id, &tmp, &call_opt,
4365
existing_call->user_data, &msg_data,
4367
if (status != PJ_SUCCESS) {
4369
/* Notify xferer about the error (if we have subscription) */
4371
status = pjsip_xfer_notify(sub, PJSIP_EVSUB_STATE_TERMINATED,
4373
if (status != PJ_SUCCESS) {
4374
pjsua_perror(THIS_FILE, "Unable to create NOTIFY to REFER",
4378
status = pjsip_xfer_send_request(sub, tdata);
4379
if (status != PJ_SUCCESS) {
4380
pjsua_perror(THIS_FILE, "Unable to send NOTIFY to REFER",
4389
/* Put the server subscription in inv_data.
4390
* Subsequent state changed in pjsua_inv_on_state_changed() will be
4391
* reported back to the server subscription.
4393
pjsua_var.calls[new_call].xfer_sub = sub;
4395
/* Put the invite_data in the subscription. */
4396
pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id,
4397
&pjsua_var.calls[new_call]);
4401
pj_log_pop_indent();
4407
* This callback is called when transaction state has changed in INVITE
4408
* session. We use this to trap:
4409
* - incoming REFER request.
4410
* - incoming MESSAGE request.
4412
static void pjsua_call_on_tsx_state_changed(pjsip_inv_session *inv,
4413
pjsip_transaction *tsx,
4418
pj_log_push_indent();
4420
call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id];
4425
if (call->inv == NULL) {
4426
/* Call has been disconnected. */
4430
/* https://trac.pjsip.org/repos/ticket/1452:
4431
* If a request is retried due to 401/407 challenge, don't process the
4432
* transaction first but wait until we've retried it.
4434
if (tsx->role == PJSIP_ROLE_UAC &&
4435
(tsx->status_code==401 || tsx->status_code==407) &&
4436
tsx->last_tx && tsx->last_tx->auth_retry)
4441
/* Notify application callback first */
4442
if (pjsua_var.ua_cfg.cb.on_call_tsx_state) {
4443
(*pjsua_var.ua_cfg.cb.on_call_tsx_state)(call->index, tsx, e);
4446
if (tsx->role==PJSIP_ROLE_UAS &&
4447
tsx->state==PJSIP_TSX_STATE_TRYING &&
4448
pjsip_method_cmp(&tsx->method, pjsip_get_refer_method())==0)
4451
* Incoming REFER request.
4453
on_call_transfered(call->inv, e->body.tsx_state.src.rdata);
4456
else if (tsx->role==PJSIP_ROLE_UAS &&
4457
tsx->state==PJSIP_TSX_STATE_TRYING &&
4458
pjsip_method_cmp(&tsx->method, &pjsip_message_method)==0)
4461
* Incoming MESSAGE request!
4463
pjsip_rx_data *rdata;
4465
pjsip_accept_hdr *accept_hdr;
4468
rdata = e->body.tsx_state.src.rdata;
4469
msg = rdata->msg_info.msg;
4471
/* Request MUST have message body, with Content-Type equal to
4474
if (pjsua_im_accept_pager(rdata, &accept_hdr) == PJ_FALSE) {
4478
pj_list_init(&hdr_list);
4479
pj_list_push_back(&hdr_list, accept_hdr);
4481
pjsip_dlg_respond( inv->dlg, rdata, PJSIP_SC_NOT_ACCEPTABLE_HERE,
4482
NULL, &hdr_list, NULL );
4486
/* Respond with 200 first, so that remote doesn't retransmit in case
4487
* the UI takes too long to process the message.
4489
status = pjsip_dlg_respond( inv->dlg, rdata, 200, NULL, NULL, NULL);
4491
/* Process MESSAGE request */
4492
pjsua_im_process_pager(call->index, &inv->dlg->remote.info_str,
4493
&inv->dlg->local.info_str, rdata);
4496
else if (tsx->role == PJSIP_ROLE_UAC &&
4497
pjsip_method_cmp(&tsx->method, &pjsip_message_method)==0)
4499
/* Handle outgoing pager status */
4500
if (tsx->status_code >= 200) {
4501
pjsua_im_data *im_data;
4503
im_data = (pjsua_im_data*) tsx->mod_data[pjsua_var.mod.id];
4504
/* im_data can be NULL if this is typing indication */
4506
if (im_data && pjsua_var.ua_cfg.cb.on_pager_status) {
4507
pjsua_var.ua_cfg.cb.on_pager_status(im_data->call_id,
4516
} else if (tsx->role == PJSIP_ROLE_UAC &&
4517
tsx->last_tx == (pjsip_tx_data*)call->hold_msg &&
4518
tsx->state >= PJSIP_TSX_STATE_COMPLETED)
4520
/* Monitor the status of call hold request */
4521
call->hold_msg = NULL;
4522
if (tsx->status_code/100 != 2) {
4523
/* Outgoing call hold failed */
4524
call->local_hold = PJ_FALSE;
4525
PJ_LOG(3,(THIS_FILE, "Error putting call %d on hold (reason=%d)",
4526
call->index, tsx->status_code));
4528
} else if (tsx->role==PJSIP_ROLE_UAS &&
4529
tsx->state==PJSIP_TSX_STATE_TRYING &&
4530
pjsip_method_cmp(&tsx->method, &pjsip_info_method)==0)
4533
* Incoming INFO request for media control.
4535
const pj_str_t STR_APPLICATION = { "application", 11};
4536
const pj_str_t STR_MEDIA_CONTROL_XML = { "media_control+xml", 17 };
4537
pjsip_rx_data *rdata = e->body.tsx_state.src.rdata;
4538
pjsip_msg_body *body = rdata->msg_info.msg->body;
4540
if (body && body->len &&
4541
pj_stricmp(&body->content_type.type, &STR_APPLICATION)==0 &&
4542
pj_stricmp(&body->content_type.subtype, &STR_MEDIA_CONTROL_XML)==0)
4544
pjsip_tx_data *tdata;
4545
pj_str_t control_st;
4548
/* Apply and answer the INFO request */
4549
pj_strset(&control_st, (char*)body->data, body->len);
4550
status = pjsua_media_apply_xml_control(call->index, &control_st);
4551
if (status == PJ_SUCCESS) {
4552
status = pjsip_endpt_create_response(tsx->endpt, rdata,
4554
if (status == PJ_SUCCESS)
4555
status = pjsip_tsx_send_msg(tsx, tdata);
4557
status = pjsip_endpt_create_response(tsx->endpt, rdata,
4559
if (status == PJ_SUCCESS)
4560
status = pjsip_tsx_send_msg(tsx, tdata);
4566
pj_log_pop_indent();
4570
/* Redirection handler */
4571
static pjsip_redirect_op pjsua_call_on_redirected(pjsip_inv_session *inv,
4572
const pjsip_uri *target,
4573
const pjsip_event *e)
4575
pjsua_call *call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id];
4576
pjsip_redirect_op op;
4578
pj_log_push_indent();
4580
if (pjsua_var.ua_cfg.cb.on_call_redirected) {
4581
op = (*pjsua_var.ua_cfg.cb.on_call_redirected)(call->index,
4584
PJ_LOG(4,(THIS_FILE, "Unhandled redirection for call %d "
4585
"(callback not implemented by application). Disconnecting "
4588
op = PJSIP_REDIRECT_STOP;
4591
pj_log_pop_indent();