Ignore:
Timestamp:
Oct 31, 2008 6:01:48 PM (15 years ago)
Author:
bennylp
Message:

Ticket #657: (Partial early media forking support) renegotiate SDP upon receiving forked 2xx response after 183 is received

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c

    r2306 r2362  
    143143struct tsx_inv_data 
    144144{ 
    145     pjsip_inv_session   *inv; 
    146     pj_bool_t            sdp_done; 
     145    pjsip_inv_session   *inv;       /* The invite session                   */ 
     146    pj_bool_t            sdp_done;  /* SDP negotiation done for this tsx?   */ 
     147    pj_str_t             done_tag;  /* To tag in RX response with answer    */ 
     148    pj_bool_t            done_early;/* Negotiation was done for early med?  */ 
    147149}; 
    148150 
     
    14081410    pj_status_t status; 
    14091411    pjsip_msg *msg; 
    1410     pjmedia_sdp_session *sdp; 
     1412    pjmedia_sdp_session *rem_sdp; 
     1413 
     1414    /* Check if SDP is present in the message. */ 
     1415 
     1416    msg = rdata->msg_info.msg; 
     1417    if (msg->body == NULL) { 
     1418        /* Message doesn't have body. */ 
     1419        return PJ_SUCCESS; 
     1420    } 
     1421 
     1422    if (pj_stricmp(&msg->body->content_type.type, &str_application) || 
     1423        pj_stricmp(&msg->body->content_type.subtype, &str_sdp)) 
     1424    { 
     1425        /* Message body is not "application/sdp" */ 
     1426        return PJMEDIA_SDP_EINSDP; 
     1427    } 
    14111428 
    14121429    /* Get/attach invite session's transaction data */ 
     
    14181435    } 
    14191436 
    1420     /* MUST NOT do multiple SDP offer/answer in a single transaction.  
     1437    /* MUST NOT do multiple SDP offer/answer in a single transaction, 
     1438     * EXCEPT if: 
     1439     *  - this is an initial UAC INVITE transaction (i.e. not re-INVITE), and 
     1440     *  - the previous negotiation was done on an early media (18x) and 
     1441     *    this response is a final/2xx response, and 
     1442     *  - the 2xx response has different To tag than the 18x response 
     1443     *    (i.e. the request has forked). 
     1444     * 
     1445     * The exception above is to add a rudimentary support for early media 
     1446     * forking (sample case: custom ringback). See this ticket for more 
     1447     * info: http://trac.pjsip.org/repos/ticket/657 
    14211448     */ 
    1422  
    14231449    if (tsx_inv_data->sdp_done) { 
    1424         if (rdata->msg_info.msg->body) { 
    1425             PJ_LOG(4,(inv->obj_name, "SDP negotiation done, message " 
    1426                       "body is ignored")); 
    1427         } 
    1428         return PJ_SUCCESS; 
    1429     } 
    1430  
    1431     /* Check if SDP is present in the message. */ 
    1432  
    1433     msg = rdata->msg_info.msg; 
    1434     if (msg->body == NULL) { 
    1435         /* Message doesn't have body. */ 
    1436         return PJ_SUCCESS; 
    1437     } 
    1438  
    1439     if (pj_stricmp(&msg->body->content_type.type, &str_application) || 
    1440         pj_stricmp(&msg->body->content_type.subtype, &str_sdp)) 
    1441     { 
    1442         /* Message body is not "application/sdp" */ 
    1443         return PJMEDIA_SDP_EINSDP; 
     1450        pj_str_t res_tag; 
     1451 
     1452        res_tag = rdata->msg_info.to->tag; 
     1453 
     1454        /* Allow final response after SDP has been negotiated in early 
     1455         * media, IF this response is a final response with different 
     1456         * tag. 
     1457         */ 
     1458        if (tsx->role == PJSIP_ROLE_UAC && 
     1459            rdata->msg_info.msg->line.status.code/100 == 2 && 
     1460            tsx_inv_data->done_early && 
     1461            pj_strcmp(&tsx_inv_data->done_tag, &res_tag)) 
     1462        { 
     1463            const pjmedia_sdp_session *reoffer_sdp = NULL; 
     1464 
     1465            PJ_LOG(4,(inv->obj_name, "Received forked final response " 
     1466                      "after SDP negotiation has been done in early " 
     1467                      "media. Renegotiating SDP..")); 
     1468 
     1469            /* Retrieve original SDP offer from INVITE request */ 
     1470            reoffer_sdp = (const pjmedia_sdp_session*)  
     1471                          tsx->last_tx->msg->body->data; 
     1472 
     1473            /* Feed the original offer to negotiator */ 
     1474            status = pjmedia_sdp_neg_modify_local_offer(inv->pool, inv->neg, 
     1475                                                        reoffer_sdp); 
     1476            if (status != PJ_SUCCESS) { 
     1477                PJ_LOG(1,(inv->obj_name, "Error updating local offer for " 
     1478                          "forked 2xx response (err=%d)", status)); 
     1479                return status; 
     1480            } 
     1481 
     1482        } else { 
     1483 
     1484            if (rdata->msg_info.msg->body) { 
     1485                PJ_LOG(4,(inv->obj_name, "SDP negotiation done, message " 
     1486                          "body is ignored")); 
     1487            } 
     1488            return PJ_SUCCESS; 
     1489        } 
    14441490    } 
    14451491 
     
    14481494    status = pjmedia_sdp_parse(rdata->tp_info.pool,  
    14491495                               (char*)msg->body->data, 
    1450                                msg->body->len, &sdp); 
     1496                               msg->body->len, &rem_sdp); 
    14511497    if (status == PJ_SUCCESS) 
    1452         status = pjmedia_sdp_validate(sdp); 
     1498        status = pjmedia_sdp_validate(rem_sdp); 
    14531499 
    14541500    if (status != PJ_SUCCESS) { 
     
    14731519        if (inv->neg == NULL) { 
    14741520            status=pjmedia_sdp_neg_create_w_remote_offer(inv->pool, NULL,  
    1475                                                          sdp, &inv->neg); 
     1521                                                         rem_sdp, &inv->neg); 
    14761522        } else { 
    1477             status=pjmedia_sdp_neg_set_remote_offer(inv->pool, inv->neg, sdp); 
     1523            status=pjmedia_sdp_neg_set_remote_offer(inv->pool, inv->neg,  
     1524                                                    rem_sdp); 
    14781525        } 
    14791526 
     
    14901537        if (mod_inv.cb.on_rx_offer && inv->notify) { 
    14911538 
    1492             (*mod_inv.cb.on_rx_offer)(inv, sdp); 
     1539            (*mod_inv.cb.on_rx_offer)(inv, rem_sdp); 
    14931540 
    14941541        } 
     
    14971544                PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER)  
    14981545    { 
     1546        int status_code; 
    14991547 
    15001548        /* This is an answer.  
     
    15051553                  pjsip_rx_data_get_info(rdata))); 
    15061554 
    1507         status = pjmedia_sdp_neg_set_remote_answer(inv->pool, inv->neg, sdp); 
     1555        status = pjmedia_sdp_neg_set_remote_answer(inv->pool, inv->neg,  
     1556                                                   rem_sdp); 
    15081557 
    15091558        if (status != PJ_SUCCESS) { 
     
    15191568        inv_negotiate_sdp(inv); 
    15201569 
    1521         /* Mark this transaction has having SDP offer/answer done. */ 
     1570        /* Mark this transaction has having SDP offer/answer done, and 
     1571         * save the reference to the To tag 
     1572         */ 
    15221573 
    15231574        tsx_inv_data->sdp_done = 1; 
     1575        status_code = rdata->msg_info.msg->line.status.code; 
     1576        tsx_inv_data->done_early = (status_code/100==1); 
     1577        pj_strdup(tsx->pool, &tsx_inv_data->done_tag,  
     1578                  &rdata->msg_info.to->tag); 
    15241579 
    15251580    } else { 
Note: See TracChangeset for help on using the changeset viewer.