Ignore:
Timestamp:
Dec 30, 2005 11:50:15 PM (18 years ago)
Author:
bennylp
Message:

Basic module, transport, and sending messages

File:
1 edited

Legend:

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

    r105 r106  
    3030#include <pj/pool.h> 
    3131#include <pj/assert.h> 
     32 
     33#if 0   // XXX JUNK 
     34    /* Initialize TLS ID for transaction lock. */ 
     35    status = pj_thread_local_alloc(&pjsip_tsx_lock_tls_id); 
     36    if (status != PJ_SUCCESS) { 
     37        goto on_error; 
     38    } 
     39    pj_thread_local_set(pjsip_tsx_lock_tls_id, NULL); 
     40 
     41 
     42    /* Create hash table for transaction. */ 
     43    endpt->tsx_table = pj_hash_create( endpt->pool, PJSIP_MAX_TSX_COUNT ); 
     44    if (!endpt->tsx_table) { 
     45        status = PJ_ENOMEM; 
     46        goto on_error; 
     47    } 
     48 
     49 
     50/* 
     51 * Create a new transaction. 
     52 * Endpoint must then initialize the new transaction as either UAS or UAC, and 
     53 * register it to the hash table. 
     54 */ 
     55PJ_DEF(pj_status_t) pjsip_endpt_create_tsx(pjsip_endpoint *endpt, 
     56                                           pjsip_transaction **p_tsx) 
     57{ 
     58    pj_pool_t *pool; 
     59 
     60    PJ_ASSERT_RETURN(endpt && p_tsx, PJ_EINVAL); 
     61 
     62    PJ_LOG(5, (THIS_FILE, "pjsip_endpt_create_tsx()")); 
     63 
     64    /* Request one pool for the transaction. Mutex is locked there. */ 
     65    pool = pjsip_endpt_create_pool(endpt, "ptsx%p",  
     66                                      PJSIP_POOL_LEN_TSX, PJSIP_POOL_INC_TSX); 
     67    if (pool == NULL) { 
     68        return PJ_ENOMEM; 
     69    } 
     70 
     71    /* Create the transaction. */ 
     72    return pjsip_tsx_create(pool, endpt, p_tsx); 
     73} 
     74 
     75 
     76/* 
     77 * Register the transaction to the endpoint. 
     78 * This will put the transaction to the transaction hash table. Before calling 
     79 * this function, the transaction must be INITIALIZED as either UAS or UAC, so 
     80 * that the transaction key is built. 
     81 */ 
     82PJ_DEF(void) pjsip_endpt_register_tsx( pjsip_endpoint *endpt, 
     83                                       pjsip_transaction *tsx) 
     84{ 
     85    PJ_LOG(5, (THIS_FILE, "pjsip_endpt_register_tsx(%s)", tsx->obj_name)); 
     86 
     87    pj_assert(tsx->transaction_key.slen != 0); 
     88    //pj_assert(tsx->state != PJSIP_TSX_STATE_NULL); 
     89 
     90    /* Lock hash table mutex. */ 
     91    pj_mutex_lock(endpt->tsx_table_mutex); 
     92 
     93    /* Register the transaction to the hash table. */ 
     94    pj_hash_set( tsx->pool, endpt->tsx_table, tsx->transaction_key.ptr, 
     95                 tsx->transaction_key.slen, tsx); 
     96 
     97    /* Unlock mutex. */ 
     98    pj_mutex_unlock(endpt->tsx_table_mutex); 
     99} 
     100 
     101/* 
     102 * Find transaction by the key. 
     103 */ 
     104PJ_DEF(pjsip_transaction*) pjsip_endpt_find_tsx( pjsip_endpoint *endpt, 
     105                                                  const pj_str_t *key ) 
     106{ 
     107    pjsip_transaction *tsx; 
     108 
     109    PJ_LOG(5, (THIS_FILE, "pjsip_endpt_find_tsx()")); 
     110 
     111    /* Start lock mutex in the endpoint. */ 
     112    pj_mutex_lock(endpt->tsx_table_mutex); 
     113 
     114    /* Find the transaction in the hash table. */ 
     115    tsx = pj_hash_get( endpt->tsx_table, key->ptr, key->slen ); 
     116 
     117    /* Unlock mutex. */ 
     118    pj_mutex_unlock(endpt->tsx_table_mutex); 
     119 
     120    return tsx; 
     121} 
     122 
     123/* 
     124 * Create key. 
     125 */ 
     126static void rdata_create_key( pjsip_rx_data *rdata) 
     127{ 
     128    pjsip_role_e role; 
     129    if (rdata->msg_info.msg->type == PJSIP_REQUEST_MSG) { 
     130        role = PJSIP_ROLE_UAS; 
     131    } else { 
     132        role = PJSIP_ROLE_UAC; 
     133    } 
     134    pjsip_tsx_create_key(rdata->tp_info.pool, &rdata->endpt_info.key, role, 
     135                         &rdata->msg_info.cseq->method, rdata); 
     136} 
     137 
     138 
     139/* 
     140 * This is the callback that is called by the transport manager when it  
     141 * receives a message from the network. 
     142 */ 
     143static void endpt_transport_callback( pjsip_endpoint *endpt, 
     144                                      pj_status_t status, 
     145                                      pjsip_rx_data *rdata ) 
     146{ 
     147    pjsip_msg *msg = rdata->msg_info.msg; 
     148    pjsip_transaction *tsx; 
     149    pj_bool_t a_new_transaction_just_been_created = PJ_FALSE; 
     150 
     151    PJ_LOG(5, (THIS_FILE, "endpt_transport_callback(rdata=%p)", rdata)); 
     152 
     153    if (status != PJ_SUCCESS) { 
     154        const char *src_addr = rdata->pkt_info.src_name; 
     155        int port = rdata->pkt_info.src_port; 
     156        PJSIP_ENDPT_LOG_ERROR((endpt, "transport", status, 
     157                               "Src.addr=%s:%d, packet:--\n" 
     158                               "%s\n" 
     159                               "-- end of packet. Error", 
     160                               src_addr, port, rdata->msg_info.msg_buf)); 
     161        return; 
     162    } 
     163 
     164    /* For response, check that the value in Via sent-by match the transport. 
     165     * If not matched, silently drop the response. 
     166     * Ref: RFC3261 Section 18.1.2 Receiving Response 
     167     */ 
     168    if (msg->type == PJSIP_RESPONSE_MSG) { 
     169        const pj_str_t *addr_addr; 
     170        int port = rdata->msg_info.via->sent_by.port; 
     171        pj_bool_t mismatch = PJ_FALSE; 
     172        if (port == 0) { 
     173            int type; 
     174            type = rdata->tp_info.transport->key.type; 
     175            port = pjsip_transport_get_default_port_for_type(type); 
     176        } 
     177        addr_addr = &rdata->tp_info.transport->local_name.host; 
     178        if (pj_strcmp(&rdata->msg_info.via->sent_by.host, addr_addr) != 0) 
     179            mismatch = PJ_TRUE; 
     180        else if (port != rdata->tp_info.transport->local_name.port) { 
     181            /* Port or address mismatch, we should discard response */ 
     182            /* But we saw one implementation (we don't want to name it to  
     183             * protect the innocence) which put wrong sent-by port although 
     184             * the "rport" parameter is correct. 
     185             * So we discard the response only if the port doesn't match 
     186             * both the port in sent-by and rport. We try to be lenient here! 
     187             */ 
     188            if (rdata->msg_info.via->rport_param != rdata->tp_info.transport->local_name.port) 
     189                mismatch = PJ_TRUE; 
     190            else { 
     191                PJ_LOG(4,(THIS_FILE, "Response %p has mismatch port in sent-by" 
     192                                    " but the rport parameter is correct", 
     193                                    rdata)); 
     194            } 
     195        } 
     196 
     197        if (mismatch) { 
     198            pjsip_event e; 
     199 
     200            PJSIP_EVENT_INIT_DISCARD_MSG(e, rdata, PJSIP_EINVALIDVIA); 
     201            endpt_do_event( endpt, &e ); 
     202            return; 
     203        } 
     204    } 
     205 
     206    /* Create key for transaction lookup. */ 
     207    rdata_create_key( rdata); 
     208 
     209    /* Find the transaction for the received message. */ 
     210    PJ_LOG(5, (THIS_FILE, "finding tsx with key=%.*s",  
     211                         rdata->endpt_info.key.slen, rdata->endpt_info.key.ptr)); 
     212 
     213    /* Start lock mutex in the endpoint. */ 
     214    pj_mutex_lock(endpt->tsx_table_mutex); 
     215 
     216    /* Find the transaction in the hash table. */ 
     217    tsx = pj_hash_get( endpt->tsx_table, rdata->endpt_info.key.ptr, rdata->endpt_info.key.slen ); 
     218 
     219    /* Unlock mutex. */ 
     220    pj_mutex_unlock(endpt->tsx_table_mutex); 
     221 
     222    /* If the transaction is not found... */ 
     223    if (tsx == NULL || tsx->state == PJSIP_TSX_STATE_TERMINATED) { 
     224 
     225        /*  
     226         * For response message, discard the message, except if the response is 
     227         * an 2xx class response to INVITE, which in this case it must be 
     228         * passed to TU to be acked. 
     229         */ 
     230        if (msg->type == PJSIP_RESPONSE_MSG) { 
     231 
     232            /* Inform TU about the 200 message, only if it's INVITE. */ 
     233            if (PJSIP_IS_STATUS_IN_CLASS(msg->line.status.code, 200) && 
     234                rdata->msg_info.cseq->method.id == PJSIP_INVITE_METHOD)  
     235            { 
     236                pjsip_event e; 
     237 
     238                /* Should not happen for UA. Tsx theoritically lives until 
     239                 * all responses are absorbed. 
     240                 */ 
     241                pj_assert(0); 
     242 
     243                PJSIP_EVENT_INIT_RX_200_MSG(e, rdata); 
     244                endpt_do_event( endpt, &e ); 
     245 
     246            } else { 
     247                /* Just discard the response, inform TU. */ 
     248                pjsip_event e; 
     249 
     250                PJSIP_EVENT_INIT_DISCARD_MSG(e, rdata,  
     251                    PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_CALL_TSX_DOES_NOT_EXIST)); 
     252                endpt_do_event( endpt, &e ); 
     253            } 
     254 
     255        /* 
     256         * For non-ACK request message, create a new transaction. 
     257         */ 
     258        } else if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) { 
     259 
     260            pj_status_t status; 
     261 
     262            /* Create transaction, mutex is locked there. */ 
     263            status = pjsip_endpt_create_tsx(endpt, &tsx); 
     264            if (status != PJ_SUCCESS) { 
     265                PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status, 
     266                                       "Unable to create transaction")); 
     267                return; 
     268            } 
     269 
     270            /* Initialize transaction as UAS. */ 
     271            pjsip_tsx_init_uas( tsx, rdata ); 
     272 
     273            /* Register transaction, mutex is locked there. */ 
     274            pjsip_endpt_register_tsx( endpt, tsx ); 
     275 
     276            a_new_transaction_just_been_created = PJ_TRUE; 
     277        } 
     278    } 
     279 
     280    /* If transaction is found (or newly created), pass the message. 
     281     * Otherwise if it's an ACK request, pass directly to TU. 
     282     */ 
     283    if (tsx && tsx->state != PJSIP_TSX_STATE_TERMINATED) { 
     284        /* Dispatch message to transaction. */ 
     285        pjsip_tsx_on_rx_msg( tsx, rdata ); 
     286 
     287    } else if (rdata->msg_info.msg->line.req.method.id == PJSIP_ACK_METHOD) { 
     288        /* 
     289         * This is an ACK message, but the INVITE transaction could not 
     290         * be found (possibly because the branch parameter in Via in ACK msg 
     291         * is different than the branch in original INVITE). This happens with 
     292         * SER! 
     293         */ 
     294        pjsip_event event; 
     295 
     296        PJSIP_EVENT_INIT_RX_ACK_MSG(event,rdata); 
     297        endpt_do_event( endpt, &event ); 
     298    } 
     299 
     300    /* 
     301     * If a new request message has just been receieved, but no modules 
     302     * seem to be able to handle the request message, then terminate the 
     303     * transaction. 
     304     * 
     305     * Ideally for cases like "unsupported method", we should be able to 
     306     * answer the request statelessly. But we can not do that since the 
     307     * endpoint shoule be able to be used as both user agent and proxy stack, 
     308     * and a proxy stack should be able to handle arbitrary methods. 
     309     */ 
     310    if (a_new_transaction_just_been_created && tsx->status_code < 100) { 
     311        /* Certainly no modules has sent any response message. 
     312         * Check that any modules has attached a module data. 
     313         */ 
     314        int i; 
     315        for (i=0; i<PJSIP_MAX_MODULE; ++i) { 
     316            if (tsx->module_data[i] != NULL) { 
     317                break; 
     318            } 
     319        } 
     320        if (i == PJSIP_MAX_MODULE) { 
     321            /* No modules have attached itself to the transaction.  
     322             * Terminate the transaction with 501/Not Implemented. 
     323             */ 
     324            pjsip_tx_data *tdata; 
     325            pj_status_t status; 
     326             
     327            if (tsx->method.id == PJSIP_OPTIONS_METHOD) { 
     328                status = pjsip_endpt_create_response(endpt, rdata, 200,  
     329                                                     &tdata); 
     330            } else { 
     331                status = pjsip_endpt_create_response(endpt, rdata,  
     332                                                     PJSIP_SC_METHOD_NOT_ALLOWED, 
     333                                                     &tdata); 
     334            } 
     335 
     336            if (status != PJ_SUCCESS) { 
     337                PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status, 
     338                                       "Unable to create response")); 
     339                return; 
     340            } 
     341 
     342            if (endpt->allow_hdr) { 
     343                pjsip_msg_add_hdr( tdata->msg,  
     344                                   pjsip_hdr_shallow_clone(tdata->pool, endpt->allow_hdr)); 
     345            } 
     346            pjsip_tsx_on_tx_msg( tsx, tdata ); 
     347 
     348        } else { 
     349            /* 
     350             * If a module has registered itself in the transaction but it 
     351             * hasn't responded the request, chances are the module wouldn't 
     352             * respond to the request at all. We terminate the request here 
     353             * with 500/Internal Server Error, to be safe. 
     354             */ 
     355            pjsip_tx_data *tdata; 
     356            pj_status_t status; 
     357 
     358            status = pjsip_endpt_create_response(endpt, rdata, 500, &tdata); 
     359            if (status != PJ_SUCCESS) { 
     360                PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status, 
     361                                       "Unable to create response")); 
     362                return; 
     363            } 
     364 
     365            pjsip_tsx_on_tx_msg(tsx, tdata); 
     366        } 
     367    } 
     368} 
     369 
     370 
     371 
     372    /* Transaction tables. */ 
     373    count = pj_hash_count(endpt->tsx_table); 
     374    PJ_LOG(3, (THIS_FILE, " Number of transactions: %u", count)); 
     375 
     376    if (count && detail) { 
     377        pj_hash_iterator_t it_val; 
     378        pj_hash_iterator_t *it; 
     379        pj_time_val now; 
     380 
     381        PJ_LOG(3, (THIS_FILE, " Dumping transaction tables:")); 
     382 
     383        pj_gettimeofday(&now); 
     384        it = pj_hash_first(endpt->tsx_table, &it_val); 
     385 
     386        while (it != NULL) { 
     387            int timeout_diff; 
     388 
     389            /* Get the transaction. No need to lock transaction's mutex 
     390             * since we already hold endpoint mutex, so that no transactions 
     391             * will be deleted. 
     392             */ 
     393            pjsip_transaction *tsx = pj_hash_this(endpt->tsx_table, it); 
     394 
     395            const char *role = (tsx->role == PJSIP_ROLE_UAS ? "UAS" : "UAC"); 
     396         
     397            if (tsx->timeout_timer._timer_id != -1) { 
     398                if (tsx->timeout_timer._timer_value.sec > now.sec) { 
     399                    timeout_diff = tsx->timeout_timer._timer_value.sec - now.sec; 
     400                } else { 
     401                    timeout_diff = now.sec - tsx->timeout_timer._timer_value.sec; 
     402                    timeout_diff = 0 - timeout_diff; 
     403                } 
     404            } else { 
     405                timeout_diff = -1; 
     406            } 
     407 
     408            PJ_LOG(3, (THIS_FILE, "  %s %s %10.*s %.9u %s t=%ds",  
     409                       tsx->obj_name, role,  
     410                       tsx->method.name.slen, tsx->method.name.ptr, 
     411                       tsx->cseq, 
     412                       pjsip_tsx_state_str(tsx->state), 
     413                       timeout_diff)); 
     414 
     415            it = pj_hash_next(endpt->tsx_table, it); 
     416        } 
     417    } 
     418 
     419 
     420 
     421#endif  // XXX JUNK 
    32422 
    33423/* Thread Local Storage ID for transaction lock (initialized by endpoint) */ 
     
    153543    return role_name[role]; 
    154544} 
     545 
     546 
     547 
     548/* 
     549 * Unregister the transaction from the hash table, and destroy the resources 
     550 * from the transaction. 
     551 */ 
     552PJ_DEF(void) pjsip_endpt_destroy_tsx( pjsip_endpoint *endpt, 
     553                                      pjsip_transaction *tsx) 
     554{ 
     555    PJ_LOG(5, (THIS_FILE, "pjsip_endpt_destroy_tsx(%s)", tsx->obj_name)); 
     556 
     557    pj_assert(tsx->state == PJSIP_TSX_STATE_DESTROYED); 
     558 
     559    /* No need to lock transaction.  
     560     * This function typically is called from the transaction callback, which 
     561     * means that transaction mutex is being held. 
     562     */ 
     563    pj_assert( pj_mutex_is_locked(tsx->mutex) ); 
     564 
     565    /* Lock endpoint. */ 
     566    pj_mutex_lock( endpt->tsx_table_mutex ); 
     567 
     568    /* Unregister from the hash table. */ 
     569    pj_hash_set( NULL, endpt->tsx_table, tsx->transaction_key.ptr,  
     570                 tsx->transaction_key.slen, NULL); 
     571 
     572    /* Unlock endpoint mutex. */ 
     573    pj_mutex_unlock( endpt->tsx_table_mutex ); 
     574 
     575    /* Destroy transaction mutex. */ 
     576    pj_mutex_destroy( tsx->mutex ); 
     577 
     578    /* Release the pool for the transaction. */ 
     579    pj_pool_release(tsx->pool); 
     580 
     581    PJ_LOG(4, (THIS_FILE, "tsx%p destroyed", tsx)); 
     582} 
     583 
    155584 
    156585 
     
    501930                                      pjsip_host_info *send_addr ) 
    502931{ 
    503     const pjsip_uri *new_request_uri, *target_uri; 
    504     const pjsip_name_addr *topmost_route_uri; 
    505     pjsip_route_hdr *first_route_hdr, *last_route_hdr; 
     932    pjsip_route_hdr *route_hdr; 
    506933     
    507934    pj_assert(tdata->msg->type == PJSIP_REQUEST_MSG); 
     
    511938     * headers from the endpoint first. 
    512939     */ 
    513     last_route_hdr = first_route_hdr =  
    514         pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, NULL); 
    515     if (first_route_hdr) { 
    516         topmost_route_uri = &first_route_hdr->name_addr; 
    517         while (last_route_hdr->next != (void*)&tdata->msg->hdr) { 
    518             pjsip_route_hdr *hdr; 
    519             hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE,  
    520                                      last_route_hdr->next); 
    521             if (!hdr) 
    522                 break; 
    523             last_route_hdr = hdr; 
    524         } 
    525     } else { 
     940    route_hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, NULL); 
     941    if (!route_hdr) { 
    526942        const pjsip_route_hdr *hdr_list; 
    527         hdr_list = (pjsip_route_hdr*)pjsip_endpt_get_routing(tsx->endpt); 
    528         if (hdr_list->next != hdr_list) { 
    529             const pjsip_route_hdr *hdr = (pjsip_route_hdr*)hdr_list->next; 
    530             first_route_hdr = NULL; 
    531             topmost_route_uri = &hdr->name_addr; 
    532             do { 
    533                 last_route_hdr = pjsip_hdr_shallow_clone(tdata->pool, hdr); 
    534                 if (first_route_hdr == NULL) 
    535                     first_route_hdr = last_route_hdr; 
    536                 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)last_route_hdr); 
    537                 hdr = hdr->next; 
    538             } while (hdr != hdr_list); 
    539         } else { 
    540             topmost_route_uri = NULL; 
    541         } 
    542     } 
    543  
    544     /* If Route headers exist, and the first element indicates loose-route, 
    545      * the URI is taken from the Request-URI, and we keep all existing Route 
    546      * headers intact. 
    547      * If Route headers exist, and the first element DOESN'T indicate loose 
    548      * route, the URI is taken from the first Route header, and remove the 
    549      * first Route header from the message. 
    550      * Otherwise if there's no Route headers, the URI is taken from the 
    551      * Request-URI. 
    552      */ 
    553     if (topmost_route_uri) { 
    554         pj_bool_t has_lr_param; 
    555  
    556         if (PJSIP_URI_SCHEME_IS_SIP(topmost_route_uri) || 
    557             PJSIP_URI_SCHEME_IS_SIPS(topmost_route_uri)) 
    558         { 
    559             const pjsip_url *url = pjsip_uri_get_uri((void*)topmost_route_uri); 
    560             has_lr_param = url->lr_param; 
    561         } else { 
    562             has_lr_param = 0; 
    563         } 
    564  
    565         if (has_lr_param) { 
    566             new_request_uri = tdata->msg->line.req.uri; 
    567             /* We shouldn't need to delete topmost Route if it has lr param. 
    568              * But seems like it breaks some proxy implementation, so we 
    569              * delete it anyway. 
    570              */ 
    571             /* 
    572             pj_list_erase(first_route_hdr); 
    573             if (first_route_hdr == last_route_hdr) 
    574                 last_route_hdr = NULL; 
    575             */ 
    576         } else { 
    577             new_request_uri = pjsip_uri_get_uri((void*)topmost_route_uri); 
    578             pj_list_erase(first_route_hdr); 
    579             if (first_route_hdr == last_route_hdr) 
    580                 last_route_hdr = NULL; 
    581         } 
    582  
    583         target_uri = (pjsip_uri*)topmost_route_uri; 
    584  
    585     } else { 
    586         target_uri = new_request_uri = tdata->msg->line.req.uri; 
    587     } 
    588  
    589     /* The target URI must be a SIP/SIPS URL so we can resolve it's address. 
    590      * Otherwise we're in trouble (i.e. there's no host part in tel: URL). 
    591      */ 
    592     pj_memset(send_addr, 0, sizeof(*send_addr)); 
    593  
    594     if (PJSIP_URI_SCHEME_IS_SIPS(target_uri)) { 
    595         pjsip_uri *uri = (pjsip_uri*) target_uri; 
    596         const pjsip_url *url = (const pjsip_url*)pjsip_uri_get_uri(uri); 
    597         send_addr->flag |= (PJSIP_TRANSPORT_SECURE | PJSIP_TRANSPORT_RELIABLE); 
    598         pj_strdup(tdata->pool, &send_addr->addr.host, &url->host); 
    599         send_addr->addr.port = url->port; 
    600         send_addr->type =  
    601             pjsip_transport_get_type_from_name(&url->transport_param); 
    602  
    603     } else if (PJSIP_URI_SCHEME_IS_SIP(target_uri)) { 
    604         pjsip_uri *uri = (pjsip_uri*) target_uri; 
    605         const pjsip_url *url = (const pjsip_url*)pjsip_uri_get_uri(uri); 
    606         pj_strdup(tdata->pool, &send_addr->addr.host, &url->host); 
    607         send_addr->addr.port = url->port; 
    608         send_addr->type =  
    609             pjsip_transport_get_type_from_name(&url->transport_param); 
    610 #if PJ_HAS_TCP 
    611         if (send_addr->type == PJSIP_TRANSPORT_TCP ||  
    612             send_addr->type == PJSIP_TRANSPORT_SCTP)  
    613         { 
    614             send_addr->flag |= PJSIP_TRANSPORT_RELIABLE; 
    615         } 
    616 #endif 
    617     } else { 
    618         pj_assert(!"Unsupported URI scheme!"); 
    619         return PJSIP_EINVALIDSCHEME; 
    620     } 
    621  
    622     /* If target URI is different than request URI, replace  
    623      * request URI add put the original URI in the last Route header. 
    624      */ 
    625     if (new_request_uri && new_request_uri!=tdata->msg->line.req.uri) { 
    626         pjsip_route_hdr *route = pjsip_route_hdr_create(tdata->pool); 
    627         route->name_addr.uri = tdata->msg->line.req.uri; 
    628         if (last_route_hdr) 
    629             pj_list_insert_after(last_route_hdr, route); 
    630         else 
    631             pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)route); 
    632         tdata->msg->line.req.uri = (pjsip_uri*)new_request_uri; 
    633     } 
    634  
    635     /* Success. */ 
    636     return PJ_SUCCESS;   
     943        const pjsip_route_hdr *hdr; 
     944        hdr_list = (const pjsip_route_hdr*)pjsip_endpt_get_routing(tsx->endpt); 
     945        hdr = hdr_list->next; 
     946        while (hdr != hdr_list { 
     947            route_hdr = pjsip_hdr_shallow_clone(tdata->pool, hdr); 
     948            pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)route_hdr); 
     949            hdr = hdr->next; 
     950        } 
     951    } 
     952 
     953    return pjsip_get_request_addr(tdata, send_addr);   
    637954} 
    638955 
Note: See TracChangeset for help on using the changeset viewer.