summaryrefslogtreecommitdiff
path: root/pjsip/src/pjsip-ua
diff options
context:
space:
mode:
authorLiong Sauw Ming <ming@teluu.com>2011-10-24 09:28:13 +0000
committerLiong Sauw Ming <ming@teluu.com>2011-10-24 09:28:13 +0000
commit2068f13bc42cf3a47374aa2765f82724a5782028 (patch)
tree29fbeaa152ab51e59b650c0d7cd83a38111e1ecc /pjsip/src/pjsip-ua
parent1c72a42676e7aa0c2ae0734549050f738f3bdf02 (diff)
Re #1395: Backport of PJSIP 1.x branch into PJSIP 2.0 trunk
* Backport of r3557:r3832 TODO: ticket #1268 (Option for automatic/manual sending of RTCP SDES/BYE for the stream) for video stream. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@3841 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjsip/src/pjsip-ua')
-rw-r--r--pjsip/src/pjsip-ua/sip_100rel.c70
-rw-r--r--pjsip/src/pjsip-ua/sip_inv.c25
2 files changed, 76 insertions, 19 deletions
diff --git a/pjsip/src/pjsip-ua/sip_100rel.c b/pjsip/src/pjsip-ua/sip_100rel.c
index 5d49731e..d2bb1d42 100644
--- a/pjsip/src/pjsip-ua/sip_100rel.c
+++ b/pjsip/src/pjsip-ua/sip_100rel.c
@@ -105,8 +105,10 @@ typedef struct uas_state_t
/* UAC state */
typedef struct uac_state_t
{
- pj_int32_t cseq;
- pj_uint32_t rseq; /* Initialized to -1 */
+ pj_str_t tag; /* To tag */
+ pj_int32_t cseq;
+ pj_uint32_t rseq; /* Initialized to -1 */
+ struct uac_state_t *next; /* next call leg */
} uac_state_t;
@@ -115,7 +117,7 @@ struct dlg_data
{
pjsip_inv_session *inv;
uas_state_t *uas_state;
- uac_state_t *uac_state;
+ uac_state_t *uac_state_list;
};
@@ -231,6 +233,8 @@ PJ_DEF(pj_status_t) pjsip_100rel_create_prack( pjsip_inv_session *inv,
pjsip_tx_data **p_tdata)
{
dlg_data *dd;
+ uac_state_t *uac_state = NULL;
+ const pj_str_t *to_tag = &rdata->msg_info.to->tag;
pjsip_transaction *tsx;
pjsip_msg *msg;
pjsip_generic_string_hdr *rseq_hdr;
@@ -261,41 +265,51 @@ PJ_DEF(pj_status_t) pjsip_100rel_create_prack( pjsip_inv_session *inv,
pjsip_msg_find_hdr_by_name(msg, &RSEQ, NULL);
if (rseq_hdr == NULL) {
PJ_LOG(4,(dd->inv->dlg->obj_name,
- "Ignoring provisional response with no RSeq header"));
+ "Ignoring 100rel response with no RSeq header"));
return PJSIP_EMISSINGHDR;
}
rseq = (pj_uint32_t) pj_strtoul(&rseq_hdr->hvalue);
+ /* Find UAC state for the specified call leg */
+ uac_state = dd->uac_state_list;
+ while (uac_state) {
+ if (pj_strcmp(&uac_state->tag, to_tag)==0)
+ break;
+ uac_state = uac_state->next;
+ }
+
/* Create new UAC state if we don't have one */
- if (dd->uac_state == NULL) {
- dd->uac_state = PJ_POOL_ZALLOC_T(dd->inv->dlg->pool,
- uac_state_t);
- dd->uac_state->cseq = rdata->msg_info.cseq->cseq;
- dd->uac_state->rseq = rseq - 1;
+ if (uac_state == NULL) {
+ uac_state = PJ_POOL_ZALLOC_T(dd->inv->dlg->pool, uac_state_t);
+ uac_state->cseq = rdata->msg_info.cseq->cseq;
+ uac_state->rseq = rseq - 1;
+ pj_strdup(dd->inv->dlg->pool, &uac_state->tag, to_tag);
+ uac_state->next = dd->uac_state_list;
+ dd->uac_state_list = uac_state;
}
- /* If this is from new INVITE transaction, reset UAC state */
- if (rdata->msg_info.cseq->cseq != dd->uac_state->cseq) {
- dd->uac_state->cseq = rdata->msg_info.cseq->cseq;
- dd->uac_state->rseq = rseq - 1;
+ /* If this is from new INVITE transaction, reset UAC state. */
+ if (rdata->msg_info.cseq->cseq != uac_state->cseq) {
+ uac_state->cseq = rdata->msg_info.cseq->cseq;
+ uac_state->rseq = rseq - 1;
}
/* Ignore provisional response retransmission */
- if (rseq <= dd->uac_state->rseq) {
+ if (rseq <= uac_state->rseq) {
/* This should have been handled before */
return PJ_EIGNORED;
/* Ignore provisional response with out-of-order RSeq */
- } else if (rseq != dd->uac_state->rseq + 1) {
+ } else if (rseq != uac_state->rseq + 1) {
PJ_LOG(4,(dd->inv->dlg->obj_name,
- "Ignoring provisional response because RSeq jump "
+ "Ignoring 100rel response because RSeq jump "
"(expecting %u, got %u)",
- dd->uac_state->rseq+1, rseq));
+ uac_state->rseq+1, rseq));
return PJ_EIGNORED;
}
/* Update our RSeq */
- dd->uac_state->rseq = rseq;
+ uac_state->rseq = rseq;
/* Create PRACK */
status = pjsip_dlg_create_request(dd->inv->dlg, &pjsip_prack_method,
@@ -303,6 +317,26 @@ PJ_DEF(pj_status_t) pjsip_100rel_create_prack( pjsip_inv_session *inv,
if (status != PJ_SUCCESS)
return status;
+ /* If this response is a forked response from a different call-leg,
+ * update the req URI (https://trac.pjsip.org/repos/ticket/1364)
+ */
+ if (pj_strcmp(&uac_state->tag, &dd->inv->dlg->remote.info->tag)) {
+ const pjsip_contact_hdr *mhdr;
+
+ mhdr = (const pjsip_contact_hdr*)
+ pjsip_msg_find_hdr(rdata->msg_info.msg,
+ PJSIP_H_CONTACT, NULL);
+ if (!mhdr || !mhdr->uri) {
+ PJ_LOG(4,(dd->inv->dlg->obj_name,
+ "Ignoring 100rel response with no or "
+ "invalid Contact header"));
+ pjsip_tx_data_dec_ref(tdata);
+ return PJ_EIGNORED;
+ }
+ tdata->msg->line.req.uri = (pjsip_uri*)
+ pjsip_uri_clone(tdata->pool, mhdr->uri);
+ }
+
/* Create RAck header */
rack.ptr = rack_buf;
rack.slen = pj_ansi_snprintf(rack.ptr, sizeof(rack_buf),
diff --git a/pjsip/src/pjsip-ua/sip_inv.c b/pjsip/src/pjsip-ua/sip_inv.c
index eca737eb..46153c9f 100644
--- a/pjsip/src/pjsip-ua/sip_inv.c
+++ b/pjsip/src/pjsip-ua/sip_inv.c
@@ -195,8 +195,18 @@ void inv_set_state(pjsip_inv_session *inv, pjsip_inv_state state,
pjsip_event *e)
{
pjsip_inv_state prev_state = inv->state;
+ pj_bool_t dont_notify = PJ_FALSE;
pj_status_t status;
+ /* Prevent STATE_CALLING from being reported more than once because
+ * of authentication
+ * https://trac.pjsip.org/repos/ticket/1318
+ */
+ if (state==PJSIP_INV_STATE_CALLING &&
+ (inv->cb_called & (1 << PJSIP_INV_STATE_CALLING)) != 0)
+ {
+ dont_notify = PJ_TRUE;
+ }
/* If state is confirmed, check that SDP negotiation is done,
* otherwise disconnect the session.
@@ -224,8 +234,11 @@ void inv_set_state(pjsip_inv_session *inv, pjsip_inv_state state,
pj_assert(inv->state != PJSIP_INV_STATE_DISCONNECTED ||
inv->cause != 0);
+ /* Mark the callback as called for this state */
+ inv->cb_called |= (1 << state);
+
/* Call on_state_changed() callback. */
- if (mod_inv.cb.on_state_changed && inv->notify)
+ if (mod_inv.cb.on_state_changed && inv->notify && !dont_notify)
(*mod_inv.cb.on_state_changed)(inv, e);
/* Only decrement when previous state is not already DISCONNECTED */
@@ -4116,6 +4129,16 @@ static void inv_on_state_confirmed( pjsip_inv_session *inv, pjsip_event *e)
/* Not Acceptable */
const pjsip_hdr *accept;
+ /* The incoming SDP is unacceptable. If the SDP negotiator
+ * state has just been changed, i.e: DONE -> REMOTE_OFFER,
+ * revert it back.
+ */
+ if (pjmedia_sdp_neg_get_state(inv->neg) ==
+ PJMEDIA_SDP_NEG_STATE_REMOTE_OFFER)
+ {
+ pjmedia_sdp_neg_cancel_offer(inv->neg);
+ }
+
status = pjsip_dlg_create_response(inv->dlg, rdata,
488, NULL, &tdata);
if (status != PJ_SUCCESS)