Ticket #917: ticket917.patch

File ticket917.patch, 2.8 KB (added by bennylp, 10 years ago)

Provisional patch, fixing the issue by inserting a hidden Route header to the CANCEL and INVITE request. This patch will not work if strict route is used, hence alternative solution is needed.

  • pjsip/src/pjsip/sip_util.c

     
    572572} 
    573573 
    574574 
     575/*  
     576 * Add hidden Route header to the CANCEL and non-2xx ACK requests so that  
     577 * the request is sent to the exact same address as the original INVITE. 
     578 * According to RFC 3263: 
     579 *  - CANCEL must be sent to the same server as INVITE. If we don't do  
     580 *    this, we will do DNS SRV for it again (since it's different  
     581 *    transaction) and it may end up being sent to a different server. 
     582 *  - same for non-2xx ACK 
     583 */ 
     584static void route_ack_cancel(const pjsip_tx_data *inv_tdata, 
     585                             pjsip_tx_data *tdata) 
     586{ 
     587    if (inv_tdata->tp_info.transport &&  
     588        pj_sockaddr_has_addr(&inv_tdata->tp_info.dst_addr)) 
     589    { 
     590        const pj_str_t str_hide = {"hidden", 6}; 
     591        pjsip_route_hdr *r; 
     592        pjsip_sip_uri *uri; 
     593        pjsip_param *p; 
     594 
     595        /* Create the Route header */ 
     596        r = pjsip_route_hdr_create(tdata->pool); 
     597 
     598        /* Init the Route URI */ 
     599        uri = pjsip_sip_uri_create(tdata->pool, PJ_FALSE); 
     600        r->name_addr.uri = (pjsip_uri*)uri; 
     601        pj_strdup2(tdata->pool, &uri->host,  
     602                   inv_tdata->tp_info.dst_name); 
     603        uri->port = inv_tdata->tp_info.dst_port; 
     604        uri->lr_param = PJ_TRUE; 
     605        pj_strdup2(tdata->pool, &uri->transport_param, 
     606                   inv_tdata->tp_info.transport->type_name); 
     607         
     608        /* Add "hide" parameter */ 
     609        p = PJ_POOL_ZALLOC_T(tdata->pool, pjsip_param); 
     610        p->name = str_hide; 
     611        pj_list_push_back(&uri->other_param, p); 
     612 
     613        /* Add the header */ 
     614        pjsip_msg_insert_first_hdr(tdata->msg, (pjsip_hdr*)r); 
     615    } 
     616} 
     617 
    575618/* 
    576619 * Construct ACK for 3xx-6xx final response (according to chapter 17.1.1 of 
    577620 * RFC3261). Note that the generation of ACK for 2xx response is different, 
     
    659702        hdr = (pjsip_hdr*) pjsip_msg_find_hdr( invite_msg, PJSIP_H_ROUTE, hdr); 
    660703    } 
    661704 
     705    /* ACK (for non-2xx response) must be sent to the same server according 
     706     * to RFC 3263, just like CANCEL. Though normally this code below is not 
     707     * required since the transaction should still have the transport  
     708     * instance, there are cases when this is not the case (e.g. when TCP 
     709     * connection is prematurely closed), so doing this wouldn't hurt. 
     710     */ 
     711    route_ack_cancel(tdata, ack); 
     712 
    662713    /* We're done. 
    663714     * "tdata" parameter now contains the ACK message. 
    664715     */ 
     
    753804            break; 
    754805    } 
    755806 
     807    /* Add hidden Route header in the request. According to RFC 3263, CANCEL 
     808     * must be sent to the same server as INVITE. If we don't do this, we 
     809     * will do DNS SRV for it again (since it's different transaction) and 
     810     * it may end up being sent to a different server. 
     811     */ 
     812    route_ack_cancel(req_tdata, cancel_tdata); 
     813 
    756814    /* Done. 
    757815     * Return the transmit buffer containing the CANCEL request. 
    758816     */