Ignore:
Timestamp:
Sep 8, 2011 4:37:43 AM (13 years ago)
Author:
bennylp
Message:

Added support for forking of reliable provisional response (100rel):

  • maintain 100rel state for each call leg (To tag)
  • added SIPp scenario
  • note that multiple SDP negotiation in 100rel response from different call leg is not supported. Especially the case when multple offers are sent in the responses are not supported (we're supposed to send answers in PRACKs, but currently we only respond to the first 100rel with SDP).

This closes #1364

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/1.x/pjsip/src/pjsip-ua/sip_100rel.c

    r3553 r3743  
    105105typedef struct uac_state_t 
    106106{ 
    107         pj_int32_t      cseq; 
    108         pj_uint32_t     rseq;   /* Initialized to -1 */ 
     107    pj_str_t            tag;    /* To tag               */ 
     108    pj_int32_t          cseq; 
     109    pj_uint32_t         rseq;   /* Initialized to -1    */ 
     110    struct uac_state_t *next;   /* next call leg        */ 
    109111} uac_state_t; 
    110112 
     
    115117        pjsip_inv_session       *inv; 
    116118        uas_state_t             *uas_state; 
    117         uac_state_t             *uac_state; 
     119        uac_state_t             *uac_state_list; 
    118120}; 
    119121 
     
    231233{ 
    232234    dlg_data *dd; 
     235    uac_state_t *uac_state = NULL; 
     236    const pj_str_t *to_tag = &rdata->msg_info.to->tag; 
    233237    pjsip_transaction *tsx; 
    234238    pjsip_msg *msg; 
     
    261265    if (rseq_hdr == NULL) { 
    262266        PJ_LOG(4,(dd->inv->dlg->obj_name,  
    263                  "Ignoring provisional response with no RSeq header")); 
     267                 "Ignoring 100rel response with no RSeq header")); 
    264268        return PJSIP_EMISSINGHDR; 
    265269    } 
    266270    rseq = (pj_uint32_t) pj_strtoul(&rseq_hdr->hvalue); 
    267271 
     272    /* Find UAC state for the specified call leg */ 
     273    uac_state = dd->uac_state_list; 
     274    while (uac_state) { 
     275        if (pj_strcmp(&uac_state->tag, to_tag)==0) 
     276            break; 
     277        uac_state = uac_state->next; 
     278    } 
     279 
    268280    /* Create new UAC state if we don't have one */ 
    269     if (dd->uac_state == NULL) { 
    270         dd->uac_state = PJ_POOL_ZALLOC_T(dd->inv->dlg->pool, 
    271                                          uac_state_t); 
    272         dd->uac_state->cseq = rdata->msg_info.cseq->cseq; 
    273         dd->uac_state->rseq = rseq - 1; 
    274     } 
    275  
    276     /* If this is from new INVITE transaction, reset UAC state */ 
    277     if (rdata->msg_info.cseq->cseq != dd->uac_state->cseq) { 
    278         dd->uac_state->cseq = rdata->msg_info.cseq->cseq; 
    279         dd->uac_state->rseq = rseq - 1; 
     281    if (uac_state == NULL) { 
     282        uac_state = PJ_POOL_ZALLOC_T(dd->inv->dlg->pool, uac_state_t); 
     283        uac_state->cseq = rdata->msg_info.cseq->cseq; 
     284        uac_state->rseq = rseq - 1; 
     285        pj_strdup(dd->inv->dlg->pool, &uac_state->tag, to_tag); 
     286        uac_state->next = dd->uac_state_list; 
     287        dd->uac_state_list = uac_state; 
     288    } 
     289 
     290    /* If this is from new INVITE transaction, reset UAC state. */ 
     291    if (rdata->msg_info.cseq->cseq != uac_state->cseq) { 
     292        uac_state->cseq = rdata->msg_info.cseq->cseq; 
     293        uac_state->rseq = rseq - 1; 
    280294    } 
    281295 
    282296    /* Ignore provisional response retransmission */ 
    283     if (rseq <= dd->uac_state->rseq) { 
     297    if (rseq <= uac_state->rseq) { 
    284298        /* This should have been handled before */ 
    285299        return PJ_EIGNORED; 
    286300 
    287301    /* Ignore provisional response with out-of-order RSeq */ 
    288     } else if (rseq != dd->uac_state->rseq + 1) { 
     302    } else if (rseq != uac_state->rseq + 1) { 
    289303        PJ_LOG(4,(dd->inv->dlg->obj_name,  
    290                  "Ignoring provisional response because RSeq jump " 
     304                 "Ignoring 100rel response because RSeq jump " 
    291305                 "(expecting %u, got %u)", 
    292                  dd->uac_state->rseq+1, rseq)); 
     306                 uac_state->rseq+1, rseq)); 
    293307        return PJ_EIGNORED; 
    294308    } 
    295309 
    296310    /* Update our RSeq */ 
    297     dd->uac_state->rseq = rseq; 
     311    uac_state->rseq = rseq; 
    298312 
    299313    /* Create PRACK */ 
     
    302316    if (status != PJ_SUCCESS) 
    303317        return status; 
     318 
     319    /* If this response is a forked response from a different call-leg, 
     320     * update the req URI (https://trac.pjsip.org/repos/ticket/1364) 
     321     */ 
     322    if (pj_strcmp(&uac_state->tag, &dd->inv->dlg->remote.info->tag)) { 
     323        const pjsip_contact_hdr *mhdr; 
     324 
     325        mhdr = (const pjsip_contact_hdr*) 
     326               pjsip_msg_find_hdr(rdata->msg_info.msg, 
     327                                  PJSIP_H_CONTACT, NULL); 
     328        if (!mhdr || !mhdr->uri) { 
     329            PJ_LOG(4,(dd->inv->dlg->obj_name, 
     330                     "Ignoring 100rel response with no or " 
     331                     "invalid Contact header")); 
     332            pjsip_tx_data_dec_ref(tdata); 
     333            return PJ_EIGNORED; 
     334        } 
     335        tdata->msg->line.req.uri = pjsip_uri_clone(tdata->pool, mhdr->uri); 
     336    } 
    304337 
    305338    /* Create RAck header */ 
Note: See TracChangeset for help on using the changeset viewer.