Ignore:
Timestamp:
Sep 24, 2008 10:10:15 AM (16 years ago)
Author:
bennylp
Message:

Ticket #635: Disconnect the other call leg when multiple 2xx/OK responses to INVITE are received due to forking

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/src/pjsip/sip_dialog.c

    r2271 r2315  
    581581{ 
    582582    pjsip_dialog *dlg; 
    583     const pjsip_route_hdr *r; 
     583    const pjsip_msg *msg = rdata->msg_info.msg; 
     584    const pjsip_hdr *end_hdr, *hdr; 
     585    const pjsip_contact_hdr *contact; 
    584586    pj_status_t status; 
    585587 
     
    588590     
    589591    /* rdata must be response message. */ 
    590     PJ_ASSERT_RETURN(rdata->msg_info.msg->type == PJSIP_RESPONSE_MSG, 
     592    PJ_ASSERT_RETURN(msg->type == PJSIP_RESPONSE_MSG, 
    591593                     PJSIP_ENOTRESPONSEMSG); 
    592594 
    593595    /* Status code MUST be 1xx (but not 100), or 2xx */ 
    594     status = rdata->msg_info.msg->line.status.code; 
     596    status = msg->line.status.code; 
    595597    PJ_ASSERT_RETURN( (status/100==1 && status!=100) || 
    596598                      (status/100==2), PJ_EBUG); 
     
    598600    /* To tag must present in the response. */ 
    599601    PJ_ASSERT_RETURN(rdata->msg_info.to->tag.slen != 0, PJSIP_EMISSINGTAG); 
     602 
     603    /* Find Contact header in the response */ 
     604    contact = (const pjsip_contact_hdr*) 
     605              pjsip_msg_find_hdr(msg, PJSIP_H_CONTACT, NULL); 
     606    if (contact == NULL) 
     607        return PJSIP_EMISSINGHDR; 
    600608 
    601609    /* Create the dialog. */ 
     
    604612        return status; 
    605613 
    606     /* Clone remote target. */ 
    607     dlg->target = (pjsip_uri*) pjsip_uri_clone(dlg->pool, first_dlg->target); 
     614    /* Set remote target from the response. */ 
     615    dlg->target = (pjsip_uri*) pjsip_uri_clone(dlg->pool, contact->uri); 
    608616 
    609617    /* Clone local info. */ 
     
    637645 
    638646    /* Dialog state depends on the response. */ 
    639     status = rdata->msg_info.msg->line.status.code/100; 
     647    status = msg->line.status.code/100; 
    640648    if (status == 1 || status == 2) 
    641649        dlg->state = PJSIP_DIALOG_STATE_ESTABLISHED; 
     
    652660                   pjsip_hdr_clone(dlg->pool, first_dlg->call_id); 
    653661 
    654     /* Duplicate Route-Set. */ 
     662    /* Get route-set from the response. */ 
    655663    pj_list_init(&dlg->route_set); 
    656     r = first_dlg->route_set.next; 
    657     while (r != &first_dlg->route_set) { 
    658         pjsip_route_hdr *h; 
    659  
    660         h = (pjsip_route_hdr*) pjsip_hdr_clone(dlg->pool, r); 
    661         pj_list_push_back(&dlg->route_set, h); 
    662  
    663         r = r->next; 
    664     } 
     664    end_hdr = &msg->hdr; 
     665    for (hdr=msg->hdr.prev; hdr!=end_hdr; hdr=hdr->prev) { 
     666        if (hdr->type == PJSIP_H_RECORD_ROUTE) { 
     667            pjsip_route_hdr *r; 
     668            r = (pjsip_route_hdr*) pjsip_hdr_clone(dlg->pool, hdr); 
     669            pjsip_routing_hdr_set_route(r); 
     670            pj_list_push_back(&dlg->route_set, r); 
     671        } 
     672    } 
     673 
    665674    //dlg->route_set_frozen = PJ_TRUE; 
    666675 
     
    18141823    } 
    18151824 
     1825    /* Handle the case of forked response, when the application creates 
     1826     * the forked dialog but not the invite session. In this case, the 
     1827     * forked 200/OK response will be unhandled, and we must send ACK 
     1828     * here. 
     1829     */ 
     1830    if (dlg->usage_cnt==0) { 
     1831        pj_status_t status; 
     1832 
     1833        if (rdata->msg_info.cseq->method.id==PJSIP_INVITE_METHOD &&  
     1834            rdata->msg_info.msg->line.status.code/100 == 2)  
     1835        { 
     1836            pjsip_tx_data *ack; 
     1837 
     1838            status = pjsip_dlg_create_request(dlg, &pjsip_ack_method, 
     1839                                              rdata->msg_info.cseq->cseq, 
     1840                                              &ack); 
     1841            if (status == PJ_SUCCESS) 
     1842                status = pjsip_dlg_send_request(dlg, ack, -1, NULL); 
     1843        } else if (rdata->msg_info.msg->line.status.code==401 || 
     1844                   rdata->msg_info.msg->line.status.code==407) 
     1845        { 
     1846            pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata); 
     1847            pjsip_tx_data *tdata; 
     1848             
     1849            status = pjsip_auth_clt_reinit_req( &dlg->auth_sess,  
     1850                                                rdata, tsx->last_tx, 
     1851                                                &tdata); 
     1852             
     1853            if (status == PJ_SUCCESS) { 
     1854                /* Re-send request. */ 
     1855                status = pjsip_dlg_send_request(dlg, tdata, -1, NULL); 
     1856            } 
     1857        } 
     1858    } 
     1859 
    18161860    /* Unhandled response does not necessarily mean error because 
    18171861       dialog usages may choose to process the transaction state instead. 
Note: See TracChangeset for help on using the changeset viewer.