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_endpoint.c

    r105 r106  
    5757    pj_str_t             name; 
    5858 
    59     /** Transaction table. */ 
    60     pj_hash_table_t     *tsx_table; 
    61  
    62     /** Mutex for transaction table. */ 
    63     pj_mutex_t          *tsx_table_mutex; 
    64  
    6559    /** Timer heap. */ 
    6660    pj_timer_heap_t     *timer_heap; 
     
    7569    pjsip_resolver_t    *resolver; 
    7670 
    77     /** Number of modules registered. */ 
    78     pj_uint32_t          mod_count; 
     71    /** Modules lock. */ 
     72    pj_rwmutex_t        *mod_mutex; 
    7973 
    8074    /** Modules. */ 
    8175    pjsip_module        *modules[PJSIP_MAX_MODULE]; 
     76 
     77    /** Module list, sorted by priority. */ 
     78    pjsip_module         module_list; 
    8279 
    8380    /** Number of supported methods. */ 
     
    128125 
    129126/* 
    130  * Initialize modules. 
    131  */ 
    132 static pj_status_t init_modules( pjsip_endpoint *endpt ) 
     127 * Register new module to the endpoint. 
     128 * The endpoint will then call the load and start function in the module to  
     129 * properly initialize the module, and assign a unique module ID for the  
     130 * module. 
     131 */ 
     132PJ_DEF(pj_status_t) pjsip_endpt_register_module( pjsip_endpoint *endpt, 
     133                                                 pjsip_module *mod ) 
     134{ 
     135    pj_status_t status = PJ_SUCCESS; 
     136    pjsip_module *m; 
     137    int i; 
     138 
     139    pj_rwmutex_lock_write(endpt->mod_mutex); 
     140 
     141    /* Make sure that this module has not been registered. */ 
     142    PJ_ASSERT_ON_FAIL(  pj_list_find_node(&endpt->module_list, mod) == NULL, 
     143                        {status = PJ_EEXISTS; goto on_return;}); 
     144 
     145    /* Find unused ID for this module. */ 
     146    for (i=0; i<PJ_ARRAY_SIZE(endpt->modules); ++i) { 
     147        if (endpt->modules[i] == NULL) 
     148            break; 
     149    } 
     150    if (i == PJ_ARRAY_SIZE(endpt->modules)) { 
     151        pj_assert(!"Too many modules registered!"); 
     152        status = PJ_ETOOMANY; 
     153        goto on_return; 
     154    } 
     155 
     156    /* Assign the ID. */ 
     157    mod->id = i; 
     158 
     159    /* Try to load the module. */ 
     160    if (mod->load) { 
     161        status = (*mod->load)(endpt); 
     162        if (status != PJ_SUCCESS) 
     163            goto on_return; 
     164    } 
     165 
     166    /* Try to start the module. */ 
     167    if (mod->start) { 
     168        status = (*mod->start)(); 
     169        if (status != PJ_SUCCESS) 
     170            goto on_return; 
     171    } 
     172 
     173    /* Save the module. */ 
     174    endpt->modules[i] = mod; 
     175 
     176    /* Put in the module list, sorted by priority. */ 
     177    m = endpt->module_list.next; 
     178    while (m != &endpt->module_list) { 
     179        if (m->priority > mod->priority) 
     180            break; 
     181        m = m->next; 
     182    } 
     183    pj_list_insert_before(m, mod); 
     184 
     185    /* Done. */ 
     186    PJ_TODO(BUILD_ALLOW_HEADER_BASED_ON_MODULES_SUPPORTED_METHODS); 
     187 
     188on_return: 
     189    pj_rwmutex_unlock_write(endpt->mod_mutex); 
     190    return status; 
     191} 
     192 
     193/* 
     194 * Unregister a module from the endpoint. 
     195 * The endpoint will then call the stop and unload function in the module to  
     196 * properly shutdown the module. 
     197 */ 
     198PJ_DEF(pj_status_t) pjsip_endpt_unregister_module( pjsip_endpoint *endpt, 
     199                                                   pjsip_module *mod ) 
    133200{ 
    134201    pj_status_t status; 
    135     unsigned i; 
    136     //pj_str_t str_COMMA = { ", ", 2 }; 
    137     extern pjsip_module aux_tsx_module; 
    138  
    139     PJ_LOG(5, (THIS_FILE, "init_modules()")); 
    140  
    141     /* Load static modules. */ 
    142     endpt->mod_count = PJSIP_MAX_MODULE; 
    143     status = register_static_modules( &endpt->mod_count, endpt->modules ); 
    144     if (status != 0) { 
    145         return status; 
    146     } 
    147  
    148     /* Add mini aux module. */ 
    149     endpt->modules[endpt->mod_count++] = &aux_tsx_module; 
    150  
    151     /* Load dynamic modules. */ 
    152     // Not supported yet! 
    153  
    154     /* Sort modules on the priority. */ 
    155     for (i=endpt->mod_count-1; i>0; --i) { 
    156         pj_uint32_t max = 0; 
    157         unsigned j; 
    158         for (j=1; j<=i; ++j) { 
    159             if (endpt->modules[j]->priority > endpt->modules[max]->priority) 
    160                 max = j; 
    161         } 
    162         if (max != i) { 
    163             pjsip_module *temp = endpt->modules[max]; 
    164             endpt->modules[max] = endpt->modules[i]; 
    165             endpt->modules[i] = temp; 
    166         } 
    167     } 
    168  
    169     /* Initialize each module. */ 
    170     for (i=0; i < endpt->mod_count; ++i) { 
    171         int j; 
    172  
    173         pjsip_module *mod = endpt->modules[i]; 
    174         if (mod->init_module) { 
    175             status = mod->init_module(endpt, mod, i); 
    176             if (status != 0) { 
    177                 return status; 
    178             } 
    179         } 
    180  
    181         /* Collect all supported methods from modules. */ 
    182         for (j=0; j<mod->method_cnt; ++j) { 
    183             unsigned k; 
    184             for (k=0; k<endpt->method_cnt; ++k) { 
    185                 if (pjsip_method_cmp(mod->methods[j], endpt->methods[k]) == 0) 
    186                     break; 
    187             } 
    188             if (k == endpt->method_cnt) { 
    189                 if (endpt->method_cnt < MAX_METHODS) { 
    190                     endpt->methods[endpt->method_cnt++] = mod->methods[j]; 
    191                 } else { 
    192                     PJ_LOG(1,(THIS_FILE, "Too many methods")); 
    193                     return -1; 
    194                 } 
    195             } 
    196         } 
    197     } 
    198  
    199     /* Create Allow header. */ 
    200     endpt->allow_hdr = pjsip_allow_hdr_create( endpt->pool ); 
    201     endpt->allow_hdr->count = endpt->method_cnt; 
    202     for (i=0; i<endpt->method_cnt; ++i) { 
    203         endpt->allow_hdr->values[i] = endpt->methods[i]->name; 
    204     } 
    205  
    206     /* Start each module. */ 
    207     for (i=0; i < endpt->mod_count; ++i) { 
    208         pjsip_module *mod = endpt->modules[i]; 
    209         if (mod->start_module) { 
    210             status = mod->start_module(mod); 
    211             if (status != 0) { 
    212                 return status; 
    213             } 
    214         } 
    215     } 
     202 
     203    pj_rwmutex_lock_write(endpt->mod_mutex); 
     204 
     205    /* Make sure the module exists in the list. */ 
     206    PJ_ASSERT_ON_FAIL(  pj_list_find_node(&endpt->module_list, mod) == mod, 
     207                        {status = PJ_ENOTFOUND;goto on_return;} ); 
     208 
     209    /* Make sure the module exists in the array. */ 
     210    PJ_ASSERT_ON_FAIL(  mod->id>=0 && mod->id<PJ_ARRAY_SIZE(endpt->modules) && 
     211                        endpt->modules[mod->id] == mod, 
     212                        {status = PJ_ENOTFOUND; goto on_return;}); 
     213 
     214    /* Try to stop the module. */ 
     215    if (mod->stop) { 
     216        status = (*mod->stop)(); 
     217        if (status != PJ_SUCCESS) goto on_return; 
     218    } 
     219 
     220    /* Try to unload the module. */ 
     221    if (mod->unload) { 
     222        status = (*mod->unload)(); 
     223        if (status != PJ_SUCCESS) goto on_return; 
     224    } 
     225 
     226    /* Remove module from array. */ 
     227    endpt->modules[mod->id] = NULL; 
     228 
     229    /* Remove module from list. */ 
     230    pj_list_erase(mod); 
    216231 
    217232    /* Done. */ 
    218     return 0; 
    219 } 
    220  
    221 /* 
    222  * Unregister the transaction from the hash table, and destroy the resources 
    223  * from the transaction. 
    224  */ 
    225 PJ_DEF(void) pjsip_endpt_destroy_tsx( pjsip_endpoint *endpt, 
    226                                       pjsip_transaction *tsx) 
    227 { 
    228     PJ_LOG(5, (THIS_FILE, "pjsip_endpt_destroy_tsx(%s)", tsx->obj_name)); 
    229  
    230     pj_assert(tsx->state == PJSIP_TSX_STATE_DESTROYED); 
    231  
    232     /* No need to lock transaction.  
    233      * This function typically is called from the transaction callback, which 
    234      * means that transaction mutex is being held. 
    235      */ 
    236     pj_assert( pj_mutex_is_locked(tsx->mutex) ); 
    237  
    238     /* Lock endpoint. */ 
    239     pj_mutex_lock( endpt->tsx_table_mutex ); 
    240  
    241     /* Unregister from the hash table. */ 
    242     pj_hash_set( NULL, endpt->tsx_table, tsx->transaction_key.ptr,  
    243                  tsx->transaction_key.slen, NULL); 
    244  
    245     /* Unlock endpoint mutex. */ 
    246     pj_mutex_unlock( endpt->tsx_table_mutex ); 
    247  
    248     /* Destroy transaction mutex. */ 
    249     pj_mutex_destroy( tsx->mutex ); 
    250  
    251     /* Release the pool for the transaction. */ 
    252     pj_pool_release(tsx->pool); 
    253  
    254     PJ_LOG(4, (THIS_FILE, "tsx%p destroyed", tsx)); 
    255 } 
    256  
    257  
    258 /* 
    259  * Receive transaction events from transactions and dispatch them to the  
    260  * modules. 
    261  */ 
    262 static void endpt_do_event( pjsip_endpoint *endpt, pjsip_event *evt) 
    263 { 
    264     unsigned i; 
    265  
    266     /* Dispatch event to modules. */ 
    267     for (i=0; i<endpt->mod_count; ++i) { 
    268         pjsip_module *mod = endpt->modules[i]; 
    269         if (mod && mod->tsx_handler) { 
    270             mod->tsx_handler( mod, evt ); 
    271         } 
    272     } 
    273  
    274     /* Destroy transaction if it is terminated. */ 
    275     if (evt->type == PJSIP_EVENT_TSX_STATE &&  
    276         evt->body.tsx_state.tsx->state == PJSIP_TSX_STATE_DESTROYED)  
    277     { 
    278         /* No need to lock mutex. Mutex is locked inside the destroy function */ 
    279         pjsip_endpt_destroy_tsx( endpt, evt->body.tsx_state.tsx ); 
    280     } 
    281 } 
    282  
    283 /* 
    284  * Receive transaction events from transactions and put in the event queue 
    285  * to be processed later. 
    286  */ 
    287 void pjsip_endpt_send_tsx_event( pjsip_endpoint *endpt, pjsip_event *evt ) 
    288 { 
    289     // Need to protect this with try/catch? 
    290     endpt_do_event(endpt, evt); 
     233    status = PJ_SUCCESS; 
     234 
     235    PJ_TODO(REMOVE_METHODS_FROM_ALLOW_HEADER_WHEN_MODULE_IS_UNREGISTERED); 
     236 
     237on_return: 
     238    pj_rwmutex_unlock_write(endpt->mod_mutex); 
     239    return status; 
    291240} 
    292241 
     
    376325 
    377326    /* Create endpoint. */ 
    378     endpt = pj_pool_calloc(pool, 1, sizeof(*endpt)); 
     327    endpt = pj_pool_zalloc(pool, sizeof(*endpt)); 
    379328    endpt->pool = pool; 
    380329    endpt->pf = pf; 
     330 
     331    /* Init modules list. */ 
     332    pj_list_init(&endpt->module_list); 
     333 
     334    /* Create R/W mutex for module manipulation. */ 
     335    status = pj_rwmutex_create(endpt->pool, "ept%p", &endpt->mod_mutex); 
     336    if (status != PJ_SUCCESS) 
     337        goto on_error; 
    381338 
    382339    /* Init parser. */ 
     
    400357    } 
    401358 
    402     /* Create mutex for the transaction table. */ 
    403     status = pj_mutex_create_recursive( endpt->pool, "mtbl%p",  
    404                                         &endpt->tsx_table_mutex); 
    405     if (status != PJ_SUCCESS) { 
    406         goto on_error; 
    407     } 
    408  
    409     /* Create hash table for transaction. */ 
    410     endpt->tsx_table = pj_hash_create( endpt->pool, PJSIP_MAX_TSX_COUNT ); 
    411     if (!endpt->tsx_table) { 
    412         status = PJ_ENOMEM; 
    413         goto on_error; 
    414     } 
    415  
    416359    /* Create timer heap to manage all timers within this endpoint. */ 
    417360    status = pj_timer_heap_create( endpt->pool, PJSIP_MAX_TIMER_COUNT,  
     
    453396    } 
    454397 
    455     /* Initialize TLS ID for transaction lock. */ 
    456     status = pj_thread_local_alloc(&pjsip_tsx_lock_tls_id); 
    457     if (status != PJ_SUCCESS) { 
    458         goto on_error; 
    459     } 
    460     pj_thread_local_set(pjsip_tsx_lock_tls_id, NULL); 
    461  
    462398    /* Initialize request headers. */ 
    463399    pj_list_init(&endpt->req_hdr); 
     
    471407    pj_list_insert_before( &endpt->req_hdr, mf_hdr); 
    472408 
    473     /* Load and init modules. */ 
    474     status = init_modules(endpt); 
    475     if (status != PJ_SUCCESS) { 
    476         PJ_LOG(4, (THIS_FILE, "pjsip_endpt_init(): error in init_modules()")); 
    477         return status; 
    478     } 
    479  
    480409    /* Done. */ 
    481410    *p_endpt = endpt; 
     
    491420        endpt->mutex = NULL; 
    492421    } 
    493     if (endpt->tsx_table_mutex) { 
    494         pj_mutex_destroy(endpt->tsx_table_mutex); 
    495         endpt->tsx_table_mutex = NULL; 
     422    if (endpt->mod_mutex) { 
     423        pj_rwmutex_destroy(endpt->mod_mutex); 
     424        endpt->mod_mutex = NULL; 
    496425    } 
    497426    pj_pool_release( endpt->pool ); 
     
    513442    /* Delete endpoint mutex. */ 
    514443    pj_mutex_destroy(endpt->mutex); 
    515  
    516     /* Delete transaction table mutex. */ 
    517     pj_mutex_destroy(endpt->tsx_table_mutex); 
    518444 
    519445    /* Finally destroy pool. */ 
     
    625551 
    626552/* 
    627  * Create a new transaction. 
    628  * Endpoint must then initialize the new transaction as either UAS or UAC, and 
    629  * register it to the hash table. 
    630  */ 
    631 PJ_DEF(pj_status_t) pjsip_endpt_create_tsx(pjsip_endpoint *endpt, 
    632                                            pjsip_transaction **p_tsx) 
    633 { 
    634     pj_pool_t *pool; 
    635  
    636     PJ_ASSERT_RETURN(endpt && p_tsx, PJ_EINVAL); 
    637  
    638     PJ_LOG(5, (THIS_FILE, "pjsip_endpt_create_tsx()")); 
    639  
    640     /* Request one pool for the transaction. Mutex is locked there. */ 
    641     pool = pjsip_endpt_create_pool(endpt, "ptsx%p",  
    642                                       PJSIP_POOL_LEN_TSX, PJSIP_POOL_INC_TSX); 
    643     if (pool == NULL) { 
    644         return PJ_ENOMEM; 
    645     } 
    646  
    647     /* Create the transaction. */ 
    648     return pjsip_tsx_create(pool, endpt, p_tsx); 
    649 } 
    650  
    651 /* 
    652  * Register the transaction to the endpoint. 
    653  * This will put the transaction to the transaction hash table. Before calling 
    654  * this function, the transaction must be INITIALIZED as either UAS or UAC, so 
    655  * that the transaction key is built. 
    656  */ 
    657 PJ_DEF(void) pjsip_endpt_register_tsx( pjsip_endpoint *endpt, 
    658                                        pjsip_transaction *tsx) 
    659 { 
    660     PJ_LOG(5, (THIS_FILE, "pjsip_endpt_register_tsx(%s)", tsx->obj_name)); 
    661  
    662     pj_assert(tsx->transaction_key.slen != 0); 
    663     //pj_assert(tsx->state != PJSIP_TSX_STATE_NULL); 
    664  
    665     /* Lock hash table mutex. */ 
    666     pj_mutex_lock(endpt->tsx_table_mutex); 
    667  
    668     /* Register the transaction to the hash table. */ 
    669     pj_hash_set( tsx->pool, endpt->tsx_table, tsx->transaction_key.ptr, 
    670                  tsx->transaction_key.slen, tsx); 
    671  
    672     /* Unlock mutex. */ 
    673     pj_mutex_unlock(endpt->tsx_table_mutex); 
    674 } 
    675  
    676 /* 
    677  * Find transaction by the key. 
    678  */ 
    679 PJ_DEF(pjsip_transaction*) pjsip_endpt_find_tsx( pjsip_endpoint *endpt, 
    680                                                   const pj_str_t *key ) 
    681 { 
    682     pjsip_transaction *tsx; 
    683  
    684     PJ_LOG(5, (THIS_FILE, "pjsip_endpt_find_tsx()")); 
    685  
    686     /* Start lock mutex in the endpoint. */ 
    687     pj_mutex_lock(endpt->tsx_table_mutex); 
    688  
    689     /* Find the transaction in the hash table. */ 
    690     tsx = pj_hash_get( endpt->tsx_table, key->ptr, key->slen ); 
    691  
    692     /* Unlock mutex. */ 
    693     pj_mutex_unlock(endpt->tsx_table_mutex); 
    694  
    695     return tsx; 
    696 } 
    697  
    698 /* 
    699  * Create key. 
    700  */ 
    701 static void rdata_create_key( pjsip_rx_data *rdata) 
    702 { 
    703     pjsip_role_e role; 
    704     if (rdata->msg_info.msg->type == PJSIP_REQUEST_MSG) { 
    705         role = PJSIP_ROLE_UAS; 
    706     } else { 
    707         role = PJSIP_ROLE_UAC; 
    708     } 
    709     pjsip_tsx_create_key(rdata->tp_info.pool, &rdata->endpt_info.key, role, 
    710                          &rdata->msg_info.cseq->method, rdata); 
    711 } 
    712  
    713 /* 
    714553 * This is the callback that is called by the transport manager when it  
    715554 * receives a message from the network. 
     
    720559{ 
    721560    pjsip_msg *msg = rdata->msg_info.msg; 
    722     pjsip_transaction *tsx; 
    723     pj_bool_t a_new_transaction_just_been_created = PJ_FALSE; 
    724561 
    725562    PJ_LOG(5, (THIS_FILE, "endpt_transport_callback(rdata=%p)", rdata)); 
    726563 
    727564    if (status != PJ_SUCCESS) { 
    728         const char *src_addr = rdata->pkt_info.src_name; 
    729         int port = rdata->pkt_info.src_port; 
    730565        PJSIP_ENDPT_LOG_ERROR((endpt, "transport", status, 
    731                                "Src.addr=%s:%d, packet:--\n" 
     566                               "Error processing packet from %s:%d, packet:--\n" 
    732567                               "%s\n" 
    733                                "-- end of packet. Error", 
    734                                src_addr, port, rdata->msg_info.msg_buf)); 
     568                               "-- end of packet.", 
     569                               rdata->pkt_info.src_name,  
     570                               rdata->pkt_info.src_port,  
     571                               rdata->msg_info.msg_buf)); 
    735572        return; 
    736573    } 
     
    741578     */ 
    742579    if (msg->type == PJSIP_RESPONSE_MSG) { 
    743         const pj_str_t *addr_addr; 
     580        const pj_str_t *local_addr; 
    744581        int port = rdata->msg_info.via->sent_by.port; 
    745582        pj_bool_t mismatch = PJ_FALSE; 
     
    749586            port = pjsip_transport_get_default_port_for_type(type); 
    750587        } 
    751         addr_addr = &rdata->tp_info.transport->local_name.host; 
    752         if (pj_strcmp(&rdata->msg_info.via->sent_by.host, addr_addr) != 0) 
     588        local_addr = &rdata->tp_info.transport->local_name.host; 
     589        if (pj_strcmp(&rdata->msg_info.via->sent_by.host, local_addr) != 0) 
    753590            mismatch = PJ_TRUE; 
    754591        else if (port != rdata->tp_info.transport->local_name.port) { 
     
    760597             * both the port in sent-by and rport. We try to be lenient here! 
    761598             */ 
    762             if (rdata->msg_info.via->rport_param != rdata->tp_info.transport->local_name.port) 
     599            if (rdata->msg_info.via->rport_param !=  
     600                rdata->tp_info.transport->local_name.port) 
    763601                mismatch = PJ_TRUE; 
    764602            else { 
    765                 PJ_LOG(4,(THIS_FILE, "Response %p has mismatch port in sent-by" 
    766                                     " but the rport parameter is correct", 
    767                                     rdata)); 
     603                PJ_LOG(4,(THIS_FILE, "Response %p from %s has mismatch port in " 
     604                                     "sent-by but the rport parameter is " 
     605                                     "correct", 
     606                                     rdata, rdata->pkt_info.src_name)); 
    768607            } 
    769608        } 
    770609 
    771610        if (mismatch) { 
    772             pjsip_event e; 
    773  
    774             PJSIP_EVENT_INIT_DISCARD_MSG(e, rdata, PJSIP_EINVALIDVIA); 
    775             endpt_do_event( endpt, &e ); 
     611            PJ_TODO(ENDPT_REPORT_WHEN_DROPPING_MESSAGE); 
     612            PJ_LOG(4,(THIS_FILE, "Dropping response from %s:%d because sent-by" 
     613                                 " is mismatch",  
     614                                 rdata->pkt_info.src_name,  
     615                                 rdata->pkt_info.src_port)); 
    776616            return; 
    777617        } 
    778     }  
    779  
    780     /* Create key for transaction lookup. */ 
    781     rdata_create_key( rdata); 
    782  
    783     /* Find the transaction for the received message. */ 
    784     PJ_LOG(5, (THIS_FILE, "finding tsx with key=%.*s",  
    785                          rdata->endpt_info.key.slen, rdata->endpt_info.key.ptr)); 
    786  
    787     /* Start lock mutex in the endpoint. */ 
    788     pj_mutex_lock(endpt->tsx_table_mutex); 
    789  
    790     /* Find the transaction in the hash table. */ 
    791     tsx = pj_hash_get( endpt->tsx_table, rdata->endpt_info.key.ptr, rdata->endpt_info.key.slen ); 
    792  
    793     /* Unlock mutex. */ 
    794     pj_mutex_unlock(endpt->tsx_table_mutex); 
    795  
    796     /* If the transaction is not found... */ 
    797     if (tsx == NULL || tsx->state == PJSIP_TSX_STATE_TERMINATED) { 
    798  
    799         /*  
    800          * For response message, discard the message, except if the response is 
    801          * an 2xx class response to INVITE, which in this case it must be 
    802          * passed to TU to be acked. 
    803          */ 
    804         if (msg->type == PJSIP_RESPONSE_MSG) { 
    805  
    806             /* Inform TU about the 200 message, only if it's INVITE. */ 
    807             if (PJSIP_IS_STATUS_IN_CLASS(msg->line.status.code, 200) && 
    808                 rdata->msg_info.cseq->method.id == PJSIP_INVITE_METHOD)  
    809             { 
    810                 pjsip_event e; 
    811  
    812                 /* Should not happen for UA. Tsx theoritically lives until 
    813                  * all responses are absorbed. 
    814                  */ 
    815                 pj_assert(0); 
    816  
    817                 PJSIP_EVENT_INIT_RX_200_MSG(e, rdata); 
    818                 endpt_do_event( endpt, &e ); 
    819  
    820             } else { 
    821                 /* Just discard the response, inform TU. */ 
    822                 pjsip_event e; 
    823  
    824                 PJSIP_EVENT_INIT_DISCARD_MSG(e, rdata,  
    825                     PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_CALL_TSX_DOES_NOT_EXIST)); 
    826                 endpt_do_event( endpt, &e ); 
    827             } 
    828  
    829         /* 
    830          * For non-ACK request message, create a new transaction. 
    831          */ 
    832         } else if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) { 
    833  
    834             pj_status_t status; 
    835  
    836             /* Create transaction, mutex is locked there. */ 
    837             status = pjsip_endpt_create_tsx(endpt, &tsx); 
    838             if (status != PJ_SUCCESS) { 
    839                 PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status, 
    840                                        "Unable to create transaction")); 
    841                 return; 
    842             } 
    843  
    844             /* Initialize transaction as UAS. */ 
    845             pjsip_tsx_init_uas( tsx, rdata ); 
    846  
    847             /* Register transaction, mutex is locked there. */ 
    848             pjsip_endpt_register_tsx( endpt, tsx ); 
    849  
    850             a_new_transaction_just_been_created = PJ_TRUE; 
     618    } 
     619 
     620 
     621    /* Distribute to modules. */ 
     622    pj_rwmutex_lock_read(endpt->mod_mutex); 
     623 
     624    if (msg->type == PJSIP_REQUEST_MSG) { 
     625        pjsip_module *mod; 
     626        pj_bool_t handled = PJ_FALSE; 
     627 
     628        mod = endpt->module_list.next; 
     629        while (mod != &endpt->module_list) { 
     630            if (mod->on_rx_request) 
     631                handled = (*mod->on_rx_request)(rdata); 
     632            if (handled) 
     633                break; 
     634            mod = mod->next; 
    851635        } 
    852     } 
    853  
    854     /* If transaction is found (or newly created), pass the message. 
    855      * Otherwise if it's an ACK request, pass directly to TU. 
    856      */ 
    857     if (tsx && tsx->state != PJSIP_TSX_STATE_TERMINATED) { 
    858         /* Dispatch message to transaction. */ 
    859         pjsip_tsx_on_rx_msg( tsx, rdata ); 
    860  
    861     } else if (rdata->msg_info.msg->line.req.method.id == PJSIP_ACK_METHOD) { 
    862         /* 
    863          * This is an ACK message, but the INVITE transaction could not 
    864          * be found (possibly because the branch parameter in Via in ACK msg 
    865          * is different than the branch in original INVITE). This happens with 
    866          * SER! 
    867          */ 
    868         pjsip_event event; 
    869  
    870         PJSIP_EVENT_INIT_RX_ACK_MSG(event,rdata); 
    871         endpt_do_event( endpt, &event ); 
    872     } 
    873  
    874     /* 
    875      * If a new request message has just been receieved, but no modules 
    876      * seem to be able to handle the request message, then terminate the 
    877      * transaction. 
    878      * 
    879      * Ideally for cases like "unsupported method", we should be able to 
    880      * answer the request statelessly. But we can not do that since the 
    881      * endpoint shoule be able to be used as both user agent and proxy stack, 
    882      * and a proxy stack should be able to handle arbitrary methods. 
    883      */ 
    884     if (a_new_transaction_just_been_created && tsx->status_code < 100) { 
    885         /* Certainly no modules has sent any response message. 
    886          * Check that any modules has attached a module data. 
    887          */ 
    888         int i; 
    889         for (i=0; i<PJSIP_MAX_MODULE; ++i) { 
    890             if (tsx->module_data[i] != NULL) { 
     636 
     637        /* No module is able to handle the request. */ 
     638        if (!handled) { 
     639            PJ_TODO(ENDPT_RESPOND_UNHANDLED_REQUEST); 
     640            PJ_LOG(4,(THIS_FILE, "Request from %s:%d was dropped/unhandled by" 
     641                                 " any modules")); 
     642        } 
     643 
     644    } else { 
     645        pjsip_module *mod; 
     646        pj_bool_t handled = PJ_FALSE; 
     647 
     648        mod = endpt->module_list.next; 
     649        while (mod != &endpt->module_list) { 
     650            if (mod->on_rx_response) 
     651                handled = (*mod->on_rx_response)(rdata); 
     652            if (handled) 
    891653                break; 
    892             } 
     654            mod = mod->next; 
    893655        } 
    894         if (i == PJSIP_MAX_MODULE) { 
    895             /* No modules have attached itself to the transaction.  
    896              * Terminate the transaction with 501/Not Implemented. 
    897              */ 
    898             pjsip_tx_data *tdata; 
    899             pj_status_t status; 
    900              
    901             if (tsx->method.id == PJSIP_OPTIONS_METHOD) { 
    902                 status = pjsip_endpt_create_response(endpt, rdata, 200,  
    903                                                      &tdata); 
    904             } else { 
    905                 status = pjsip_endpt_create_response(endpt, rdata,  
    906                                                      PJSIP_SC_METHOD_NOT_ALLOWED, 
    907                                                      &tdata); 
    908             } 
    909  
    910             if (status != PJ_SUCCESS) { 
    911                 PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status, 
    912                                        "Unable to create response")); 
    913                 return; 
    914             } 
    915  
    916             if (endpt->allow_hdr) { 
    917                 pjsip_msg_add_hdr( tdata->msg,  
    918                                    pjsip_hdr_shallow_clone(tdata->pool, endpt->allow_hdr)); 
    919             } 
    920             pjsip_tsx_on_tx_msg( tsx, tdata ); 
    921  
    922         } else { 
    923             /* 
    924              * If a module has registered itself in the transaction but it 
    925              * hasn't responded the request, chances are the module wouldn't 
    926              * respond to the request at all. We terminate the request here 
    927              * with 500/Internal Server Error, to be safe. 
    928              */ 
    929             pjsip_tx_data *tdata; 
    930             pj_status_t status; 
    931  
    932             status = pjsip_endpt_create_response(endpt, rdata, 500, &tdata); 
    933             if (status != PJ_SUCCESS) { 
    934                 PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status, 
    935                                        "Unable to create response")); 
    936                 return; 
    937             } 
    938  
    939             pjsip_tsx_on_tx_msg(tsx, tdata); 
     656 
     657        if (!handled) { 
     658            PJ_LOG(4,(THIS_FILE, "Response from %s:%d was dropped/unhandled by" 
     659                                 " any modules")); 
    940660        } 
    941661    } 
     662 
     663    pj_rwmutex_unlock_read(endpt->mod_mutex); 
    942664} 
    943665 
     
    984706 * Find/create transport. 
    985707 */ 
    986 PJ_DEF(pj_status_t) pjsip_endpt_alloc_transport( pjsip_endpoint *endpt, 
     708PJ_DEF(pj_status_t) pjsip_endpt_acquire_transport(pjsip_endpoint *endpt, 
    987709                                                  pjsip_transport_type_e type, 
    988                                                   const pj_sockaddr *remote, 
     710                                                  const pj_sockaddr_t *remote, 
    989711                                                  int addr_len, 
    990                                                   pjsip_transport **p_transport) 
    991 { 
    992     PJ_LOG(5, (THIS_FILE, "pjsip_endpt_alloc_transport()")); 
    993     return pjsip_tpmgr_alloc_transport( endpt->transport_mgr, type,  
    994                                         remote, addr_len, p_transport); 
     712                                                  pjsip_transport **transport) 
     713{ 
     714    PJ_LOG(5, (THIS_FILE, "pjsip_endpt_acquire_transport()")); 
     715    return pjsip_tpmgr_acquire_transport(endpt->transport_mgr, type,  
     716                                         remote, addr_len, transport); 
    995717} 
    996718 
     
    1050772{ 
    1051773#if PJ_LOG_MAX_LEVEL >= 3 
    1052     unsigned count; 
    1053  
    1054774    PJ_LOG(5, (THIS_FILE, "pjsip_endpt_dump()")); 
    1055775 
     
    1066786               pj_pool_get_capacity(endpt->pool), 
    1067787               pj_pool_get_used_size(endpt->pool))); 
    1068  
    1069     /* Transaction tables. */ 
    1070     count = pj_hash_count(endpt->tsx_table); 
    1071     PJ_LOG(3, (THIS_FILE, " Number of transactions: %u", count)); 
    1072  
    1073     if (count && detail) { 
    1074         pj_hash_iterator_t it_val; 
    1075         pj_hash_iterator_t *it; 
    1076         pj_time_val now; 
    1077  
    1078         PJ_LOG(3, (THIS_FILE, " Dumping transaction tables:")); 
    1079  
    1080         pj_gettimeofday(&now); 
    1081         it = pj_hash_first(endpt->tsx_table, &it_val); 
    1082  
    1083         while (it != NULL) { 
    1084             int timeout_diff; 
    1085  
    1086             /* Get the transaction. No need to lock transaction's mutex 
    1087              * since we already hold endpoint mutex, so that no transactions 
    1088              * will be deleted. 
    1089              */ 
    1090             pjsip_transaction *tsx = pj_hash_this(endpt->tsx_table, it); 
    1091  
    1092             const char *role = (tsx->role == PJSIP_ROLE_UAS ? "UAS" : "UAC"); 
    1093          
    1094             if (tsx->timeout_timer._timer_id != -1) { 
    1095                 if (tsx->timeout_timer._timer_value.sec > now.sec) { 
    1096                     timeout_diff = tsx->timeout_timer._timer_value.sec - now.sec; 
    1097                 } else { 
    1098                     timeout_diff = now.sec - tsx->timeout_timer._timer_value.sec; 
    1099                     timeout_diff = 0 - timeout_diff; 
    1100                 } 
    1101             } else { 
    1102                 timeout_diff = -1; 
    1103             } 
    1104  
    1105             PJ_LOG(3, (THIS_FILE, "  %s %s %10.*s %.9u %s t=%ds",  
    1106                        tsx->obj_name, role,  
    1107                        tsx->method.name.slen, tsx->method.name.ptr, 
    1108                        tsx->cseq, 
    1109                        pjsip_tsx_state_str(tsx->state), 
    1110                        timeout_diff)); 
    1111  
    1112             it = pj_hash_next(endpt->tsx_table, it); 
    1113         } 
    1114     } 
    1115788 
    1116789    /* Transports.  
Note: See TracChangeset for help on using the changeset viewer.