Changeset 4175
- Timestamp:
- Jun 22, 2012 8:53:11 AM (12 years ago)
- Location:
- pjproject/trunk/pjsip
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
r4173 r4175 4085 4085 * Send response to incoming INVITE request. Depending on the status 4086 4086 * code specified as parameter, this function may send provisional 4087 * response, establish the call, or terminate the call. 4087 * response, establish the call, or terminate the call. See also 4088 * #pjsua_call_answer2(). 4088 4089 * 4089 4090 * @param call_id Incoming call identification. … … 4103 4104 4104 4105 /** 4105 * Send response to incoming INVITE request. Depending on the status 4106 * code specified as parameter, this function may send provisional 4107 * response, establish the call, or terminate the call. 4106 * Send response to incoming INVITE request with call setting param. 4107 * Depending on the status code specified as parameter, this function may 4108 * send provisional response, establish the call, or terminate the call. 4109 * Notes about call setting: 4110 * - if call setting is changed in the subsequent call to this function, 4111 * only the first call setting supplied will applied. So normally 4112 * application will not supply call setting before getting confirmation 4113 * from the user. 4114 * - if no call setting is supplied when SDP has to be sent, i.e: answer 4115 * with status code 183 or 2xx, the default call setting will be used, 4116 * check #pjsua_call_setting for its default values. 4108 4117 * 4109 4118 * @param call_id Incoming call identification. -
pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h
r4173 r4175 109 109 pj_str_t *reason; /**< Answer's reason phrase. */ 110 110 unsigned code; /**< Answer's status code. */ 111 pjsua_call_setting *opt; /**< Answer's call setting. */ 111 112 } call_answer; 112 113 … … 121 122 unsigned index; /**< Index in pjsua array. */ 122 123 pjsua_call_setting opt; /**< Call setting. */ 124 pj_bool_t opt_inited;/**< Initial call setting has been set, 125 to avoid different opt in answer. */ 123 126 pjsip_inv_session *inv; /**< The invite session. */ 124 127 void *user_data; /**< User/application data. */ … … 171 174 struct { 172 175 call_answer answers;/**< A list of call answers. */ 176 pjsip_dialog *replaced_dlg; /**< Replaced dialog. */ 173 177 } inc_call; 174 178 } call_var; -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
r4173 r4175 807 807 808 808 809 static pj_status_t process_incoming_call_replace(pjsua_call *call, 810 pjsip_dialog *replaced_dlg) 811 { 812 pjsip_inv_session *replaced_inv; 813 struct pjsua_call *replaced_call; 814 pjsip_tx_data *tdata; 815 pj_status_t status; 816 817 /* Get the invite session in the dialog */ 818 replaced_inv = pjsip_dlg_get_inv_session(replaced_dlg); 819 820 /* Get the replaced call instance */ 821 replaced_call = (pjsua_call*) replaced_dlg->mod_data[pjsua_var.mod.id]; 822 823 /* Notify application */ 824 if (pjsua_var.ua_cfg.cb.on_call_replaced) 825 pjsua_var.ua_cfg.cb.on_call_replaced(replaced_call->index, 826 call->index); 827 828 PJ_LOG(4,(THIS_FILE, "Answering replacement call %d with 200/OK", 829 call->index)); 830 831 /* Answer the new call with 200 response */ 832 status = pjsip_inv_answer(call->inv, 200, NULL, NULL, &tdata); 833 if (status == PJ_SUCCESS) 834 status = pjsip_inv_send_msg(call->inv, tdata); 835 836 if (status != PJ_SUCCESS) 837 pjsua_perror(THIS_FILE, "Error answering session", status); 838 839 /* Note that inv may be invalid if 200/OK has caused error in 840 * starting the media. 841 */ 842 843 PJ_LOG(4,(THIS_FILE, "Disconnecting replaced call %d", 844 replaced_call->index)); 845 846 /* Disconnect replaced invite session */ 847 status = pjsip_inv_end_session(replaced_inv, PJSIP_SC_GONE, NULL, 848 &tdata); 849 if (status == PJ_SUCCESS && tdata) 850 status = pjsip_inv_send_msg(replaced_inv, tdata); 851 852 if (status != PJ_SUCCESS) 853 pjsua_perror(THIS_FILE, "Error terminating session", status); 854 855 return status; 856 } 857 858 859 static void process_pending_call_answer(pjsua_call *call) 860 { 861 struct call_answer *answer, *next; 862 863 answer = call->async_call.call_var.inc_call.answers.next; 864 while (answer != &call->async_call.call_var.inc_call.answers) { 865 next = answer->next; 866 pjsua_call_answer2(call->index, answer->opt, answer->code, 867 answer->reason, answer->msg_data); 868 869 /* Call might have been disconnected if application is answering 870 * with 200/OK and the media failed to start. 871 * See pjsua_call_answer() below. 872 */ 873 if (!call->inv || !call->inv->pool_prov) 874 break; 875 876 pj_list_erase(answer); 877 answer = next; 878 } 879 } 880 881 809 882 /* Incoming call callback when media transport creation is completed. */ 810 883 static pj_status_t … … 890 963 call->med_ch_cb = NULL; 891 964 892 if (status == PJ_SUCCESS && 893 !pj_list_empty(&call->async_call.call_var.inc_call.answers)) 894 { 895 struct call_answer *answer, *next; 896 897 answer = call->async_call.call_var.inc_call.answers.next; 898 while (answer != &call->async_call.call_var.inc_call.answers) { 899 next = answer->next; 900 pjsua_call_answer(call_id, answer->code, answer->reason, 901 answer->msg_data); 902 903 /* Call might have been disconnected if application is answering 904 * with 200/OK and the media failed to start. 905 * See pjsua_call_answer() below. 906 */ 907 if (!call->inv || !call->inv->pool_prov) 908 break; 909 910 pj_list_erase(answer); 911 answer = next; 912 } 965 /* Finish any pending process */ 966 if (status == PJ_SUCCESS) { 967 if (call->async_call.call_var.inc_call.replaced_dlg) { 968 /* Process pending call replace */ 969 pjsip_dialog *replaced_dlg = 970 call->async_call.call_var.inc_call.replaced_dlg; 971 process_incoming_call_replace(call, replaced_dlg); 972 } else { 973 /* Process pending call answers */ 974 process_pending_call_answer(call); 975 } 913 976 } 914 977 … … 1253 1316 pj_list_init(&call->async_call.call_var.inc_call.answers); 1254 1317 1255 /* Init media channel */ 1256 status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAS, 1257 call->secure_level, 1258 rdata->tp_info.pool, 1259 offer, 1260 &sip_err_code, PJ_TRUE, 1261 &on_incoming_call_med_tp_complete); 1262 if (status == PJ_SUCCESS) { 1263 status = on_incoming_call_med_tp_complete(call_id, NULL); 1264 if (status != PJ_SUCCESS) { 1265 sip_err_code = PJSIP_SC_NOT_ACCEPTABLE; 1266 /* Since the call invite's state is still PJSIP_INV_STATE_NULL, 1267 * the invite session was not ended in 1268 * on_incoming_call_med_tp_complete(), so we need to send 1269 * a response message and terminate the invite here. 1270 */ 1271 pjsip_dlg_respond(dlg, rdata, sip_err_code, NULL, NULL, NULL); 1272 pjsip_inv_terminate(call->inv, sip_err_code, PJ_FALSE); 1273 call->inv = NULL; 1318 /* Init media channel, only when there is offer or call replace request. 1319 * For incoming call without SDP offer, media channel init will be done 1320 * in pjsua_call_answer(), see ticket #1526. 1321 */ 1322 if (offer || replaced_dlg) { 1323 status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAS, 1324 call->secure_level, 1325 rdata->tp_info.pool, 1326 offer, 1327 &sip_err_code, PJ_TRUE, 1328 &on_incoming_call_med_tp_complete); 1329 if (status == PJ_SUCCESS) { 1330 status = on_incoming_call_med_tp_complete(call_id, NULL); 1331 if (status != PJ_SUCCESS) { 1332 sip_err_code = PJSIP_SC_NOT_ACCEPTABLE; 1333 /* Since the call invite's state is still PJSIP_INV_STATE_NULL, 1334 * the invite session was not ended in 1335 * on_incoming_call_med_tp_complete(), so we need to send 1336 * a response message and terminate the invite here. 1337 */ 1338 pjsip_dlg_respond(dlg, rdata, sip_err_code, NULL, NULL, NULL); 1339 pjsip_inv_terminate(call->inv, sip_err_code, PJ_FALSE); 1340 call->inv = NULL; 1341 goto on_return; 1342 } 1343 } else if (status != PJ_EPENDING) { 1344 pjsua_perror(THIS_FILE, "Error initializing media channel", status); 1345 pjsip_dlg_respond(dlg, rdata, sip_err_code, NULL, NULL, NULL); 1346 pjsip_inv_terminate(call->inv, sip_err_code, PJ_FALSE); 1347 call->inv = NULL; 1274 1348 goto on_return; 1275 } 1276 } else if (status != PJ_EPENDING) { 1277 pjsua_perror(THIS_FILE, "Error initializing media channel", status); 1278 pjsip_dlg_respond(dlg, rdata, sip_err_code, NULL, NULL, NULL); 1279 pjsip_inv_terminate(call->inv, sip_err_code, PJ_FALSE); 1280 call->inv = NULL; 1281 goto on_return; 1349 } 1282 1350 } 1283 1351 … … 1365 1433 /* Check if this request should replace existing call */ 1366 1434 if (replaced_dlg) { 1367 pjsip_inv_session *replaced_inv; 1368 struct pjsua_call *replaced_call; 1369 pjsip_tx_data *tdata; 1370 1371 /* Get the invite session in the dialog */ 1372 replaced_inv = pjsip_dlg_get_inv_session(replaced_dlg); 1373 1374 /* Get the replaced call instance */ 1375 replaced_call = (pjsua_call*) replaced_dlg->mod_data[pjsua_var.mod.id]; 1376 1377 /* Notify application */ 1378 if (pjsua_var.ua_cfg.cb.on_call_replaced) 1379 pjsua_var.ua_cfg.cb.on_call_replaced(replaced_call->index, 1380 call_id); 1381 1382 PJ_LOG(4,(THIS_FILE, "Answering replacement call %d with 200/OK", 1383 call_id)); 1384 1385 /* Answer the new call with 200 response */ 1386 status = pjsip_inv_answer(inv, 200, NULL, NULL, &tdata); 1387 if (status == PJ_SUCCESS) 1388 status = pjsip_inv_send_msg(inv, tdata); 1389 1390 if (status != PJ_SUCCESS) 1391 pjsua_perror(THIS_FILE, "Error answering session", status); 1392 1393 /* Note that inv may be invalid if 200/OK has caused error in 1394 * starting the media. 1435 /* Process call replace. If the media channel init has been completed, 1436 * just process now, otherwise, just queue the replaced dialog so 1437 * it will be processed once the media channel async init is finished 1438 * successfully. 1395 1439 */ 1396 1397 PJ_LOG(4,(THIS_FILE, "Disconnecting replaced call %d", 1398 replaced_call->index)); 1399 1400 /* Disconnect replaced invite session */ 1401 status = pjsip_inv_end_session(replaced_inv, PJSIP_SC_GONE, NULL, 1402 &tdata); 1403 if (status == PJ_SUCCESS && tdata) 1404 status = pjsip_inv_send_msg(replaced_inv, tdata); 1405 1406 if (status != PJ_SUCCESS) 1407 pjsua_perror(THIS_FILE, "Error terminating session", status); 1408 1409 1440 if (call->med_ch_cb == NULL) { 1441 process_incoming_call_replace(call, replaced_dlg); 1442 } else { 1443 call->async_call.call_var.inc_call.replaced_dlg = replaced_dlg; 1444 } 1410 1445 } else { 1411 1412 1446 /* Notify application if on_incoming_call() is overriden, 1413 1447 * otherwise hangup the call with 480 … … 1822 1856 1823 1857 1858 /* Media channel init callback for pjsua_call_answer(). */ 1859 static pj_status_t 1860 on_answer_call_med_tp_complete(pjsua_call_id call_id, 1861 const pjsua_med_tp_state_info *info) 1862 { 1863 pjsua_call *call = &pjsua_var.calls[call_id]; 1864 pjmedia_sdp_session *sdp; 1865 int sip_err_code = (info? info->sip_err_code: 0); 1866 pj_status_t status = (info? info->status: PJ_SUCCESS); 1867 1868 PJSUA_LOCK(); 1869 1870 if (status != PJ_SUCCESS) { 1871 pjsua_perror(THIS_FILE, "Error initializing media channel", status); 1872 goto on_return; 1873 } 1874 1875 /* pjsua_media_channel_deinit() has been called. */ 1876 if (call->async_call.med_ch_deinit) { 1877 pjsua_media_channel_deinit(call->index); 1878 call->med_ch_cb = NULL; 1879 PJSUA_UNLOCK(); 1880 return PJ_SUCCESS; 1881 } 1882 1883 status = pjsua_media_channel_create_sdp(call_id, 1884 call->async_call.dlg->pool, 1885 NULL, &sdp, &sip_err_code); 1886 if (status != PJ_SUCCESS) { 1887 pjsua_perror(THIS_FILE, "Error creating SDP answer", status); 1888 goto on_return; 1889 } 1890 1891 status = pjsip_inv_set_local_sdp(call->inv, sdp); 1892 if (status != PJ_SUCCESS) { 1893 pjsua_perror(THIS_FILE, "Error setting local SDP", status); 1894 sip_err_code = PJSIP_SC_NOT_ACCEPTABLE_HERE; 1895 goto on_return; 1896 } 1897 1898 on_return: 1899 if (status != PJ_SUCCESS) { 1900 /* If the callback is called from pjsua_call_on_incoming(), the 1901 * invite's state is PJSIP_INV_STATE_NULL, so the invite session 1902 * will be terminated later, otherwise we end the session here. 1903 */ 1904 if (call->inv->state > PJSIP_INV_STATE_NULL) { 1905 pjsip_tx_data *tdata; 1906 pj_status_t status_; 1907 1908 status_ = pjsip_inv_end_session(call->inv, sip_err_code, NULL, 1909 &tdata); 1910 if (status_ == PJ_SUCCESS && tdata) 1911 status_ = pjsip_inv_send_msg(call->inv, tdata); 1912 } 1913 1914 pjsua_media_channel_deinit(call->index); 1915 } 1916 1917 /* Set the callback to NULL to indicate that the async operation 1918 * has completed. 1919 */ 1920 call->med_ch_cb = NULL; 1921 1922 /* Finish any pending process */ 1923 if (status == PJ_SUCCESS) { 1924 /* Process pending call answers */ 1925 process_pending_call_answer(call); 1926 } 1927 1928 PJSUA_UNLOCK(); 1929 return status; 1930 } 1931 1932 1824 1933 /* 1825 1934 * Send response to incoming INVITE request. … … 1858 1967 goto on_return; 1859 1968 1860 /* Apply call setting */ 1861 status = apply_call_setting(call, opt, NULL); 1862 if (status != PJ_SUCCESS) { 1863 pjsua_perror(THIS_FILE, "Failed to apply call setting", status); 1864 goto on_return; 1969 /* Apply call setting, only if status code is 1xx or 2xx. */ 1970 if (opt && code < 300) { 1971 /* Check if it has not been set previously or it is different to 1972 * the previous one. 1973 */ 1974 if (!call->opt_inited) { 1975 call->opt_inited = PJ_TRUE; 1976 apply_call_setting(call, opt, NULL); 1977 } else if (pj_memcmp(opt, &call->opt, sizeof(*opt)) != 0) { 1978 /* Warn application about call setting inconsistency */ 1979 PJ_LOG(2,(THIS_FILE, "The call setting changes is ignored.")); 1980 } 1865 1981 } 1866 1982 1867 1983 PJSUA_LOCK(); 1984 1985 /* Ticket #1526: When the incoming call contains no SDP offer, the media 1986 * channel may have not been initialized at this stage. The media channel 1987 * will be initialized here (along with SDP local offer generation) when 1988 * the following conditions are met: 1989 * - no pending media channel init 1990 * - local SDP has not been generated 1991 * - call setting has just been set, or SDP offer needs to be sent, i.e: 1992 * answer code 183 or 2xx is issued 1993 */ 1994 if (!call->med_ch_cb && 1995 (call->opt_inited || (code==183 && code/100==2)) && 1996 (!call->inv->neg || 1997 pjmedia_sdp_neg_get_state(call->inv->neg) == 1998 PJMEDIA_SDP_NEG_STATE_NULL)) 1999 { 2000 /* Mark call setting as initialized as it is just about to be used 2001 * for initializing the media channel. 2002 */ 2003 call->opt_inited = PJ_TRUE; 2004 2005 status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAC, 2006 call->secure_level, 2007 dlg->pool, 2008 NULL, NULL, PJ_TRUE, 2009 &on_answer_call_med_tp_complete); 2010 if (status == PJ_SUCCESS) { 2011 status = on_answer_call_med_tp_complete(call->index, NULL); 2012 if (status != PJ_SUCCESS) 2013 goto on_return; 2014 } else if (status != PJ_EPENDING) { 2015 pjsua_perror(THIS_FILE, "Error initializing media channel", status); 2016 goto on_return; 2017 } 2018 } 2019 1868 2020 /* If media transport creation is not yet completed, we will answer 1869 2021 * the call in the media transport creation callback instead. … … 1877 2029 answer = PJ_POOL_ZALLOC_T(call->inv->pool_prov, struct call_answer); 1878 2030 answer->code = code; 2031 if (opt) { 2032 answer->opt = PJ_POOL_ZALLOC_T(call->inv->pool_prov, 2033 pjsua_call_setting); 2034 *answer->opt = *opt; 2035 } 1879 2036 if (reason) { 1880 2037 pj_strdup(call->inv->pool_prov, answer->reason, reason); … … 1892 2049 return status; 1893 2050 } 2051 1894 2052 PJSUA_UNLOCK(); 1895 2053
Note: See TracChangeset
for help on using the changeset viewer.