summaryrefslogtreecommitdiff
path: root/pjsip
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2008-06-19 14:10:28 +0000
committerBenny Prijono <bennylp@teluu.com>2008-06-19 14:10:28 +0000
commitd43d82894549014370cb97b965c6e36862d1950d (patch)
tree1836d2d968ec65411952f9961ac4a1cf545752d1 /pjsip
parentf1b535a4586b205974f01e017f89f6e2dd0e52ba (diff)
Ticket #549: major modification in media transport API to support more offer/answer scenarios
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@2032 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjsip')
-rw-r--r--pjsip/include/pjsua-lib/pjsua_internal.h23
-rw-r--r--pjsip/src/pjsua-lib/pjsua_call.c119
-rw-r--r--pjsip/src/pjsua-lib/pjsua_media.c67
3 files changed, 99 insertions, 110 deletions
diff --git a/pjsip/include/pjsua-lib/pjsua_internal.h b/pjsip/include/pjsua-lib/pjsua_internal.h
index 766d8782..b3aeb11b 100644
--- a/pjsip/include/pjsua-lib/pjsua_internal.h
+++ b/pjsip/include/pjsua-lib/pjsua_internal.h
@@ -27,6 +27,22 @@
PJ_BEGIN_DECL
/**
+ * Media transport state.
+ */
+typedef enum pjsua_med_tp_st
+{
+ /** Not initialized */
+ PJSUA_MED_TP_IDLE,
+
+ /** Initialized (media_create() has been called) */
+ PJSUA_MED_TP_INIT,
+
+ /** Running (media_start() has been called) */
+ PJSUA_MED_TP_RUNNING
+
+} pjsua_med_tp_st;
+
+/**
* Structure to be attached to invite dialog.
* Given a dialog "dlg", application can retrieve this structure
* by accessing dlg->mod_data[pjsua.mod.id].
@@ -52,8 +68,9 @@ typedef struct pjsua_call
pjsip_evsub *xfer_sub; /**< Xfer server subscription, if this
call was triggered by xfer. */
pjmedia_transport *med_tp; /**< Current media transport. */
- pj_status_t med_tp_st; /**< Media transport status. */
+ pj_status_t med_tp_ready;/**< Media transport status. */
pjmedia_transport *med_orig; /**< Original media transport */
+ pjsua_med_tp_st med_tp_st; /**< Media transport state */
pj_timer_entry refresh_tm;/**< Timer to send re-INVITE. */
pj_timer_entry hangup_tm; /**< Timer to hangup call. */
pj_stun_nat_type rem_nat_type; /**< NAT type of remote endpoint. */
@@ -321,6 +338,8 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata);
pj_status_t pjsua_media_channel_init(pjsua_call_id call_id,
pjsip_role_e role,
int security_level,
+ pj_pool_t *tmp_pool,
+ const pjmedia_sdp_session *rem_sdp,
int *sip_err_code);
pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id,
pj_pool_t *pool,
@@ -328,7 +347,7 @@ pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id,
pjmedia_sdp_session **p_sdp,
int *sip_err_code);
pj_status_t pjsua_media_channel_update(pjsua_call_id call_id,
- pjmedia_sdp_session *local_sdp,
+ const pjmedia_sdp_session *local_sdp,
const pjmedia_sdp_session *remote_sdp);
pj_status_t pjsua_media_channel_deinit(pjsua_call_id call_id);
diff --git a/pjsip/src/pjsua-lib/pjsua_call.c b/pjsip/src/pjsua-lib/pjsua_call.c
index f20fea0f..d01b5f6e 100644
--- a/pjsip/src/pjsua-lib/pjsua_call.c
+++ b/pjsip/src/pjsua-lib/pjsua_call.c
@@ -212,8 +212,6 @@ PJ_DEF(pj_status_t) pjsua_enum_calls( pjsua_call_id ids[],
}
-#define LATE_SDP 0
-
/* Allocate one call id */
static pjsua_call_id alloc_call_id(void)
{
@@ -287,6 +285,7 @@ static int get_secure_level(pjsua_acc_id acc_id, const pj_str_t *dst_uri)
return 0;
}
+/*
static int call_get_secure_level(pjsua_call *call)
{
if (call->inv->dlg->secure)
@@ -316,6 +315,7 @@ static int call_get_secure_level(pjsua_call *call)
return 0;
}
+*/
/*
@@ -449,23 +449,20 @@ PJ_DEF(pj_status_t) pjsua_call_make_call( pjsua_acc_id acc_id,
/* Init media channel */
status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAC,
- call->secure_level, NULL);
+ call->secure_level, dlg->pool,
+ NULL, NULL);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "Error initializing media channel", status);
goto on_error;
}
- /* Create SDP offer */
-#if LATE_SDP
- offer = NULL;
-#else
- status = pjsua_media_channel_create_sdp(call->index, dlg->pool, NULL,
+ /* Create offer */
+ status = pjsua_media_channel_create_sdp(call->index, dlg->pool, NULL,
&offer, NULL);
if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "pjmedia unable to create SDP", status);
+ pjsua_perror(THIS_FILE, "Error initializing media channel", status);
goto on_error;
}
-#endif
/* Create the INVITE session: */
options |= PJSIP_INV_SUPPORT_100REL;
@@ -718,18 +715,6 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
else
call->secure_level = 0;
- /* Init media channel */
- status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAS,
- call->secure_level, &sip_err_code);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Error initializing media channel", status);
- pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata,
- sip_err_code, NULL,
- NULL, NULL);
- PJSUA_UNLOCK();
- return PJ_TRUE;
- }
-
/* Parse SDP from incoming request */
if (rdata->msg_info.msg->body) {
status = pjmedia_sdp_parse(rdata->tp_info.pool,
@@ -739,9 +724,8 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
const pj_str_t reason = pj_str("Bad SDP");
pjsua_perror(THIS_FILE, "Error parsing SDP in incoming INVITE",
status);
- pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 400, &reason,
- NULL, NULL);
- pjsua_media_channel_deinit(call->index);
+ pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata, 400,
+ &reason, NULL, NULL, NULL);
PJSUA_UNLOCK();
return PJ_TRUE;
}
@@ -761,19 +745,31 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
offer = NULL;
}
- /* Get media capability from media endpoint: */
+ /* Init media channel */
+ status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAS,
+ call->secure_level,
+ rdata->tp_info.pool, offer,
+ &sip_err_code);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "Error initializing media channel", status);
+ pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata,
+ sip_err_code, NULL, NULL, NULL, NULL);
+ PJSUA_UNLOCK();
+ return PJ_TRUE;
+ }
+
+ /* Create answer */
status = pjsua_media_channel_create_sdp(call->index, rdata->tp_info.pool,
offer, &answer, &sip_err_code);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "Error creating SDP answer", status);
- pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata,
- sip_err_code, NULL,
- NULL, NULL);
- pjsua_media_channel_deinit(call->index);
+ pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata,
+ sip_err_code, NULL, NULL, NULL, NULL);
PJSUA_UNLOCK();
return PJ_TRUE;
}
+
/* Verify that we can handle the request. */
options |= PJSIP_INV_SUPPORT_100REL;
if (pjsua_var.acc[acc_id].cfg.require_100rel)
@@ -794,10 +790,9 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
NULL, NULL);
} else {
-
/* Respond with 500 (Internal Server Error) */
- pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 500, NULL,
- NULL, NULL);
+ pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata, 500, NULL,
+ NULL, NULL, NULL);
}
pjsua_media_channel_deinit(call->index);
@@ -1474,18 +1469,6 @@ PJ_DEF(pj_status_t) pjsua_call_reinvite( pjsua_call_id call_id,
return PJSIP_ESESSIONSTATE;
}
- /* Update call secure level */
- call->secure_level = call_get_secure_level(call);
-
- /* Init media channel */
- status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAC,
- call->secure_level, NULL);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Error initializing media channel", status);
- pjsip_dlg_dec_lock(dlg);
- return PJSIP_ESESSIONSTATE;
- }
-
/* Create SDP */
PJ_UNUSED_ARG(unhold);
PJ_TODO(create_active_inactive_sdp_based_on_unhold_arg);
@@ -1547,18 +1530,6 @@ PJ_DEF(pj_status_t) pjsua_call_update( pjsua_call_id call_id,
if (status != PJ_SUCCESS)
return status;
- /* Update call's secure level */
- call->secure_level = call_get_secure_level(call);
-
- /* Init media channel */
- status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAC,
- call->secure_level, NULL);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Error initializing media channel", status);
- pjsip_dlg_dec_lock(dlg);
- return PJSIP_ESESSIONSTATE;
- }
-
/* Create SDP */
status = pjsua_media_channel_create_sdp(call->index, call->inv->pool,
NULL, &sdp, NULL);
@@ -1569,7 +1540,9 @@ PJ_DEF(pj_status_t) pjsua_call_update( pjsua_call_id call_id,
return status;
}
- /* Create re-INVITE with new offer */
+ update_sdp_version(call, sdp);
+
+ /* Create UPDATE with new offer */
status = pjsip_inv_update(call->inv, NULL, sdp, &tdata);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "Unable to create UPDATE request", status);
@@ -2537,8 +2510,7 @@ static void pjsua_call_on_media_update(pjsip_inv_session *inv,
pj_status_t status)
{
pjsua_call *call;
- const pjmedia_sdp_session *c_local;
- pjmedia_sdp_session *local_sdp;
+ const pjmedia_sdp_session *local_sdp;
const pjmedia_sdp_session *remote_sdp;
PJSUA_LOCK();
@@ -2567,7 +2539,7 @@ static void pjsua_call_on_media_update(pjsip_inv_session *inv,
/* Get local and remote SDP */
- status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &c_local);
+ status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &local_sdp);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE,
"Unable to retrieve currently active local SDP",
@@ -2576,7 +2548,6 @@ static void pjsua_call_on_media_update(pjsip_inv_session *inv,
PJSUA_UNLOCK();
return;
}
- local_sdp = (pjmedia_sdp_session*) c_local;
status = pjmedia_sdp_neg_get_active_remote(call->inv->neg, &remote_sdp);
if (status != PJ_SUCCESS) {
@@ -2712,18 +2683,6 @@ static void pjsua_call_on_rx_offer(pjsip_inv_session *inv,
PJ_LOG(4,(THIS_FILE, "Call %d: received updated media offer",
call->index));
- /* Update call's secure level */
- call->secure_level = call_get_secure_level(call);
-
- /* Init media channel */
- status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAS,
- call->secure_level, NULL);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Error initializing media channel", status);
- PJSUA_UNLOCK();
- return;
- }
-
status = pjsua_media_channel_create_sdp(call->index, call->inv->pool,
offer, &answer, NULL);
}
@@ -2768,18 +2727,6 @@ static void pjsua_call_on_create_offer(pjsip_inv_session *inv,
PJ_LOG(4,(THIS_FILE, "Call %d: asked to send a new offer",
call->index));
- /* Update call's secure level */
- call->secure_level = call_get_secure_level(call);
-
- /* Init media channel */
- status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAC,
- call->secure_level, NULL);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Error initializing media channel", status);
- PJSUA_UNLOCK();
- return;
- }
-
status = pjsua_media_channel_create_sdp(call->index, call->inv->pool,
NULL, offer, NULL);
}
diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c
index c678341d..a0c992c3 100644
--- a/pjsip/src/pjsua-lib/pjsua_media.c
+++ b/pjsip/src/pjsua-lib/pjsua_media.c
@@ -652,7 +652,7 @@ static void on_ice_complete(pjmedia_transport *tp,
switch (op) {
case PJ_ICE_STRANS_OP_INIT:
- pjsua_var.calls[id].med_tp_st = result;
+ pjsua_var.calls[id].med_tp_ready = result;
break;
case PJ_ICE_STRANS_OP_NEGOTIATION:
if (result != PJ_SUCCESS) {
@@ -752,7 +752,7 @@ static pj_status_t create_ice_media_transports(void)
pj_bzero(&ice_cb, sizeof(pjmedia_ice_cb));
ice_cb.on_ice_complete = &on_ice_complete;
pj_ansi_snprintf(name, sizeof(name), "icetp%02d", i);
- pjsua_var.calls[i].med_tp_st = PJ_EPENDING;
+ pjsua_var.calls[i].med_tp_ready = PJ_EPENDING;
comp_cnt = 1;
if (PJMEDIA_ADVERTISE_RTCP)
@@ -769,14 +769,14 @@ static pj_status_t create_ice_media_transports(void)
/* Wait until transport is initialized, or time out */
PJSUA_UNLOCK();
- while (pjsua_var.calls[i].med_tp_st == PJ_EPENDING) {
+ while (pjsua_var.calls[i].med_tp_ready == PJ_EPENDING) {
pjsua_handle_events(100);
}
PJSUA_LOCK();
- if (pjsua_var.calls[i].med_tp_st != PJ_SUCCESS) {
+ if (pjsua_var.calls[i].med_tp_ready != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "Error initializing ICE media transport",
- pjsua_var.calls[i].med_tp_st);
- status = pjsua_var.calls[i].med_tp_st;
+ pjsua_var.calls[i].med_tp_ready);
+ status = pjsua_var.calls[i].med_tp_ready;
goto on_error;
}
@@ -847,15 +847,18 @@ PJ_DEF(pj_status_t) pjsua_media_transports_create(
pj_status_t pjsua_media_channel_init(pjsua_call_id call_id,
pjsip_role_e role,
int security_level,
+ pj_pool_t *tmp_pool,
+ const pjmedia_sdp_session *rem_sdp,
int *sip_err_code)
{
+ enum { MEDIA_IDX = 0 };
pjsua_call *call = &pjsua_var.calls[call_id];
+ pj_status_t status;
#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
pjsua_acc *acc = &pjsua_var.acc[call->acc_id];
pjmedia_srtp_setting srtp_opt;
pjmedia_transport *srtp;
- pj_status_t status;
#endif
PJ_UNUSED_ARG(role);
@@ -904,6 +907,16 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id,
PJ_UNUSED_ARG(security_level);
#endif
+ /* Create the media transport */
+ status = pjmedia_transport_media_create(call->med_tp, tmp_pool, 0,
+ rem_sdp, MEDIA_IDX);
+ if (status != PJ_SUCCESS) {
+ if (sip_err_code) *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE;
+ pjsua_media_channel_deinit(call_id);
+ return status;
+ }
+
+ call->med_tp_st = PJSUA_MED_TP_INIT;
return PJ_SUCCESS;
}
@@ -926,6 +939,18 @@ pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id,
return PJ_EBUSY;
}
+ /* Create media if it's not created. This could happen when call is
+ * currently on-hold
+ */
+ if (call->med_tp_st == PJSUA_MED_TP_IDLE) {
+ pjsip_role_e role;
+ role = (rem_sdp ? PJSIP_ROLE_UAS : PJSIP_ROLE_UAC);
+ status = pjsua_media_channel_init(call_id, role, call->secure_level,
+ pool, rem_sdp, sip_status_code);
+ if (status != PJ_SUCCESS)
+ return status;
+ }
+
/* Get media socket info */
pjmedia_transport_info_init(&tpinfo);
pjmedia_transport_get_info(call->med_tp, &tpinfo);
@@ -935,7 +960,7 @@ pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id,
&tpinfo.sock_info, &sdp);
if (status != PJ_SUCCESS) {
if (sip_status_code) *sip_status_code = 500;
- goto on_error;
+ return status;
}
/* Add NAT info in the SDP */
@@ -963,20 +988,15 @@ pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id,
}
/* Give the SDP to media transport */
- status = pjmedia_transport_media_create(call->med_tp, pool, 0,
- sdp, rem_sdp, MEDIA_IDX);
+ status = pjmedia_transport_encode_sdp(call->med_tp, pool, sdp, rem_sdp,
+ MEDIA_IDX);
if (status != PJ_SUCCESS) {
if (sip_status_code) *sip_status_code = PJSIP_SC_NOT_ACCEPTABLE;
- goto on_error;
+ return status;
}
*p_sdp = sdp;
return PJ_SUCCESS;
-
-on_error:
- pjsua_media_channel_deinit(call_id);
- return status;
-
}
@@ -984,9 +1004,6 @@ static void stop_media_session(pjsua_call_id call_id)
{
pjsua_call *call = &pjsua_var.calls[call_id];
- //see ticket #525
- //pjmedia_transport_media_stop(call->med_tp);
-
if (call->conf_slot != PJSUA_INVALID_ID) {
if (pjsua_var.mconf) {
pjsua_conf_remove_port(call->conf_slot);
@@ -1016,7 +1033,10 @@ pj_status_t pjsua_media_channel_deinit(pjsua_call_id call_id)
stop_media_session(call_id);
- pjmedia_transport_media_stop(call->med_tp);
+ if (call->med_tp_st != PJSUA_MED_TP_IDLE) {
+ pjmedia_transport_media_stop(call->med_tp);
+ call->med_tp_st = PJSUA_MED_TP_IDLE;
+ }
if (call->med_orig && call->med_tp != call->med_orig) {
pjmedia_transport_close(call->med_tp);
@@ -1048,7 +1068,7 @@ static void dtmf_callback(pjmedia_stream *strm, void *user_data,
pj_status_t pjsua_media_channel_update(pjsua_call_id call_id,
- pjmedia_sdp_session *local_sdp,
+ const pjmedia_sdp_session *local_sdp,
const pjmedia_sdp_session *remote_sdp)
{
unsigned i;
@@ -1112,6 +1132,7 @@ pj_status_t pjsua_media_channel_update(pjsua_call_id call_id,
/* Shutdown transport's session */
pjmedia_transport_media_stop(call->med_tp);
+ call->med_tp_st = PJSUA_MED_TP_IDLE;
/* No need because we need keepalive? */
@@ -1122,13 +1143,15 @@ pj_status_t pjsua_media_channel_update(pjsua_call_id call_id,
}
} else {
- /* Start media transport */
+ /* Start/restart media transport */
status = pjmedia_transport_media_start(call->med_tp,
call->inv->pool,
local_sdp, remote_sdp, 0);
if (status != PJ_SUCCESS)
return status;
+ call->med_tp_st = PJSUA_MED_TP_RUNNING;
+
/* Override ptime, if this option is specified. */
if (pjsua_var.media_cfg.ptime != 0) {
si->param->setting.frm_per_pkt = (pj_uint8_t)