summaryrefslogtreecommitdiff
path: root/pjsip/src/pjsip/sip_endpoint.c
diff options
context:
space:
mode:
Diffstat (limited to 'pjsip/src/pjsip/sip_endpoint.c')
-rw-r--r--pjsip/src/pjsip/sip_endpoint.c645
1 files changed, 159 insertions, 486 deletions
diff --git a/pjsip/src/pjsip/sip_endpoint.c b/pjsip/src/pjsip/sip_endpoint.c
index b3fa2f8c..61741cb1 100644
--- a/pjsip/src/pjsip/sip_endpoint.c
+++ b/pjsip/src/pjsip/sip_endpoint.c
@@ -56,12 +56,6 @@ struct pjsip_endpoint
/** Name. */
pj_str_t name;
- /** Transaction table. */
- pj_hash_table_t *tsx_table;
-
- /** Mutex for transaction table. */
- pj_mutex_t *tsx_table_mutex;
-
/** Timer heap. */
pj_timer_heap_t *timer_heap;
@@ -74,12 +68,15 @@ struct pjsip_endpoint
/** DNS Resolver. */
pjsip_resolver_t *resolver;
- /** Number of modules registered. */
- pj_uint32_t mod_count;
+ /** Modules lock. */
+ pj_rwmutex_t *mod_mutex;
/** Modules. */
pjsip_module *modules[PJSIP_MAX_MODULE];
+ /** Module list, sorted by priority. */
+ pjsip_module module_list;
+
/** Number of supported methods. */
unsigned method_cnt;
@@ -127,167 +124,119 @@ static void pool_callback( pj_pool_t *pool, pj_size_t size )
/*
- * Initialize modules.
+ * Register new module to the endpoint.
+ * The endpoint will then call the load and start function in the module to
+ * properly initialize the module, and assign a unique module ID for the
+ * module.
*/
-static pj_status_t init_modules( pjsip_endpoint *endpt )
+PJ_DEF(pj_status_t) pjsip_endpt_register_module( pjsip_endpoint *endpt,
+ pjsip_module *mod )
{
- pj_status_t status;
- unsigned i;
- //pj_str_t str_COMMA = { ", ", 2 };
- extern pjsip_module aux_tsx_module;
-
- PJ_LOG(5, (THIS_FILE, "init_modules()"));
-
- /* Load static modules. */
- endpt->mod_count = PJSIP_MAX_MODULE;
- status = register_static_modules( &endpt->mod_count, endpt->modules );
- if (status != 0) {
- return status;
- }
+ pj_status_t status = PJ_SUCCESS;
+ pjsip_module *m;
+ int i;
- /* Add mini aux module. */
- endpt->modules[endpt->mod_count++] = &aux_tsx_module;
+ pj_rwmutex_lock_write(endpt->mod_mutex);
- /* Load dynamic modules. */
- // Not supported yet!
+ /* Make sure that this module has not been registered. */
+ PJ_ASSERT_ON_FAIL( pj_list_find_node(&endpt->module_list, mod) == NULL,
+ {status = PJ_EEXISTS; goto on_return;});
- /* Sort modules on the priority. */
- for (i=endpt->mod_count-1; i>0; --i) {
- pj_uint32_t max = 0;
- unsigned j;
- for (j=1; j<=i; ++j) {
- if (endpt->modules[j]->priority > endpt->modules[max]->priority)
- max = j;
- }
- if (max != i) {
- pjsip_module *temp = endpt->modules[max];
- endpt->modules[max] = endpt->modules[i];
- endpt->modules[i] = temp;
- }
+ /* Find unused ID for this module. */
+ for (i=0; i<PJ_ARRAY_SIZE(endpt->modules); ++i) {
+ if (endpt->modules[i] == NULL)
+ break;
+ }
+ if (i == PJ_ARRAY_SIZE(endpt->modules)) {
+ pj_assert(!"Too many modules registered!");
+ status = PJ_ETOOMANY;
+ goto on_return;
}
- /* Initialize each module. */
- for (i=0; i < endpt->mod_count; ++i) {
- int j;
-
- pjsip_module *mod = endpt->modules[i];
- if (mod->init_module) {
- status = mod->init_module(endpt, mod, i);
- if (status != 0) {
- return status;
- }
- }
+ /* Assign the ID. */
+ mod->id = i;
- /* Collect all supported methods from modules. */
- for (j=0; j<mod->method_cnt; ++j) {
- unsigned k;
- for (k=0; k<endpt->method_cnt; ++k) {
- if (pjsip_method_cmp(mod->methods[j], endpt->methods[k]) == 0)
- break;
- }
- if (k == endpt->method_cnt) {
- if (endpt->method_cnt < MAX_METHODS) {
- endpt->methods[endpt->method_cnt++] = mod->methods[j];
- } else {
- PJ_LOG(1,(THIS_FILE, "Too many methods"));
- return -1;
- }
- }
- }
+ /* Try to load the module. */
+ if (mod->load) {
+ status = (*mod->load)(endpt);
+ if (status != PJ_SUCCESS)
+ goto on_return;
}
- /* Create Allow header. */
- endpt->allow_hdr = pjsip_allow_hdr_create( endpt->pool );
- endpt->allow_hdr->count = endpt->method_cnt;
- for (i=0; i<endpt->method_cnt; ++i) {
- endpt->allow_hdr->values[i] = endpt->methods[i]->name;
+ /* Try to start the module. */
+ if (mod->start) {
+ status = (*mod->start)();
+ if (status != PJ_SUCCESS)
+ goto on_return;
}
- /* Start each module. */
- for (i=0; i < endpt->mod_count; ++i) {
- pjsip_module *mod = endpt->modules[i];
- if (mod->start_module) {
- status = mod->start_module(mod);
- if (status != 0) {
- return status;
- }
- }
+ /* Save the module. */
+ endpt->modules[i] = mod;
+
+ /* Put in the module list, sorted by priority. */
+ m = endpt->module_list.next;
+ while (m != &endpt->module_list) {
+ if (m->priority > mod->priority)
+ break;
+ m = m->next;
}
+ pj_list_insert_before(m, mod);
/* Done. */
- return 0;
+ PJ_TODO(BUILD_ALLOW_HEADER_BASED_ON_MODULES_SUPPORTED_METHODS);
+
+on_return:
+ pj_rwmutex_unlock_write(endpt->mod_mutex);
+ return status;
}
/*
- * Unregister the transaction from the hash table, and destroy the resources
- * from the transaction.
+ * Unregister a module from the endpoint.
+ * The endpoint will then call the stop and unload function in the module to
+ * properly shutdown the module.
*/
-PJ_DEF(void) pjsip_endpt_destroy_tsx( pjsip_endpoint *endpt,
- pjsip_transaction *tsx)
+PJ_DEF(pj_status_t) pjsip_endpt_unregister_module( pjsip_endpoint *endpt,
+ pjsip_module *mod )
{
- PJ_LOG(5, (THIS_FILE, "pjsip_endpt_destroy_tsx(%s)", tsx->obj_name));
-
- pj_assert(tsx->state == PJSIP_TSX_STATE_DESTROYED);
-
- /* No need to lock transaction.
- * This function typically is called from the transaction callback, which
- * means that transaction mutex is being held.
- */
- pj_assert( pj_mutex_is_locked(tsx->mutex) );
-
- /* Lock endpoint. */
- pj_mutex_lock( endpt->tsx_table_mutex );
+ pj_status_t status;
- /* Unregister from the hash table. */
- pj_hash_set( NULL, endpt->tsx_table, tsx->transaction_key.ptr,
- tsx->transaction_key.slen, NULL);
+ pj_rwmutex_lock_write(endpt->mod_mutex);
- /* Unlock endpoint mutex. */
- pj_mutex_unlock( endpt->tsx_table_mutex );
+ /* Make sure the module exists in the list. */
+ PJ_ASSERT_ON_FAIL( pj_list_find_node(&endpt->module_list, mod) == mod,
+ {status = PJ_ENOTFOUND;goto on_return;} );
- /* Destroy transaction mutex. */
- pj_mutex_destroy( tsx->mutex );
+ /* Make sure the module exists in the array. */
+ PJ_ASSERT_ON_FAIL( mod->id>=0 && mod->id<PJ_ARRAY_SIZE(endpt->modules) &&
+ endpt->modules[mod->id] == mod,
+ {status = PJ_ENOTFOUND; goto on_return;});
- /* Release the pool for the transaction. */
- pj_pool_release(tsx->pool);
+ /* Try to stop the module. */
+ if (mod->stop) {
+ status = (*mod->stop)();
+ if (status != PJ_SUCCESS) goto on_return;
+ }
- PJ_LOG(4, (THIS_FILE, "tsx%p destroyed", tsx));
-}
+ /* Try to unload the module. */
+ if (mod->unload) {
+ status = (*mod->unload)();
+ if (status != PJ_SUCCESS) goto on_return;
+ }
+ /* Remove module from array. */
+ endpt->modules[mod->id] = NULL;
-/*
- * Receive transaction events from transactions and dispatch them to the
- * modules.
- */
-static void endpt_do_event( pjsip_endpoint *endpt, pjsip_event *evt)
-{
- unsigned i;
+ /* Remove module from list. */
+ pj_list_erase(mod);
- /* Dispatch event to modules. */
- for (i=0; i<endpt->mod_count; ++i) {
- pjsip_module *mod = endpt->modules[i];
- if (mod && mod->tsx_handler) {
- mod->tsx_handler( mod, evt );
- }
- }
+ /* Done. */
+ status = PJ_SUCCESS;
- /* Destroy transaction if it is terminated. */
- if (evt->type == PJSIP_EVENT_TSX_STATE &&
- evt->body.tsx_state.tsx->state == PJSIP_TSX_STATE_DESTROYED)
- {
- /* No need to lock mutex. Mutex is locked inside the destroy function */
- pjsip_endpt_destroy_tsx( endpt, evt->body.tsx_state.tsx );
- }
-}
+ PJ_TODO(REMOVE_METHODS_FROM_ALLOW_HEADER_WHEN_MODULE_IS_UNREGISTERED);
-/*
- * Receive transaction events from transactions and put in the event queue
- * to be processed later.
- */
-void pjsip_endpt_send_tsx_event( pjsip_endpoint *endpt, pjsip_event *evt )
-{
- // Need to protect this with try/catch?
- endpt_do_event(endpt, evt);
+on_return:
+ pj_rwmutex_unlock_write(endpt->mod_mutex);
+ return status;
}
/*
@@ -375,10 +324,18 @@ PJ_DEF(pj_status_t) pjsip_endpt_create(pj_pool_factory *pf,
return PJ_ENOMEM;
/* Create endpoint. */
- endpt = pj_pool_calloc(pool, 1, sizeof(*endpt));
+ endpt = pj_pool_zalloc(pool, sizeof(*endpt));
endpt->pool = pool;
endpt->pf = pf;
+ /* Init modules list. */
+ pj_list_init(&endpt->module_list);
+
+ /* Create R/W mutex for module manipulation. */
+ status = pj_rwmutex_create(endpt->pool, "ept%p", &endpt->mod_mutex);
+ if (status != PJ_SUCCESS)
+ goto on_error;
+
/* Init parser. */
init_sip_parser();
@@ -399,20 +356,6 @@ PJ_DEF(pj_status_t) pjsip_endpt_create(pj_pool_factory *pf,
goto on_error;
}
- /* Create mutex for the transaction table. */
- status = pj_mutex_create_recursive( endpt->pool, "mtbl%p",
- &endpt->tsx_table_mutex);
- if (status != PJ_SUCCESS) {
- goto on_error;
- }
-
- /* Create hash table for transaction. */
- endpt->tsx_table = pj_hash_create( endpt->pool, PJSIP_MAX_TSX_COUNT );
- if (!endpt->tsx_table) {
- status = PJ_ENOMEM;
- goto on_error;
- }
-
/* Create timer heap to manage all timers within this endpoint. */
status = pj_timer_heap_create( endpt->pool, PJSIP_MAX_TIMER_COUNT,
&endpt->timer_heap);
@@ -452,13 +395,6 @@ PJ_DEF(pj_status_t) pjsip_endpt_create(pj_pool_factory *pf,
goto on_error;
}
- /* Initialize TLS ID for transaction lock. */
- status = pj_thread_local_alloc(&pjsip_tsx_lock_tls_id);
- if (status != PJ_SUCCESS) {
- goto on_error;
- }
- pj_thread_local_set(pjsip_tsx_lock_tls_id, NULL);
-
/* Initialize request headers. */
pj_list_init(&endpt->req_hdr);
@@ -470,13 +406,6 @@ PJ_DEF(pj_status_t) pjsip_endpt_create(pj_pool_factory *pf,
mf_hdr->ivalue = PJSIP_MAX_FORWARDS_VALUE;
pj_list_insert_before( &endpt->req_hdr, mf_hdr);
- /* Load and init modules. */
- status = init_modules(endpt);
- if (status != PJ_SUCCESS) {
- PJ_LOG(4, (THIS_FILE, "pjsip_endpt_init(): error in init_modules()"));
- return status;
- }
-
/* Done. */
*p_endpt = endpt;
return status;
@@ -490,9 +419,9 @@ on_error:
pj_mutex_destroy(endpt->mutex);
endpt->mutex = NULL;
}
- if (endpt->tsx_table_mutex) {
- pj_mutex_destroy(endpt->tsx_table_mutex);
- endpt->tsx_table_mutex = NULL;
+ if (endpt->mod_mutex) {
+ pj_rwmutex_destroy(endpt->mod_mutex);
+ endpt->mod_mutex = NULL;
}
pj_pool_release( endpt->pool );
@@ -513,9 +442,6 @@ PJ_DEF(void) pjsip_endpt_destroy(pjsip_endpoint *endpt)
/* Delete endpoint mutex. */
pj_mutex_destroy(endpt->mutex);
- /* Delete transaction table mutex. */
- pj_mutex_destroy(endpt->tsx_table_mutex);
-
/* Finally destroy pool. */
pj_pool_release(endpt->pool);
}
@@ -624,93 +550,6 @@ PJ_DEF(void) pjsip_endpt_cancel_timer( pjsip_endpoint *endpt,
}
/*
- * Create a new transaction.
- * Endpoint must then initialize the new transaction as either UAS or UAC, and
- * register it to the hash table.
- */
-PJ_DEF(pj_status_t) pjsip_endpt_create_tsx(pjsip_endpoint *endpt,
- pjsip_transaction **p_tsx)
-{
- pj_pool_t *pool;
-
- PJ_ASSERT_RETURN(endpt && p_tsx, PJ_EINVAL);
-
- PJ_LOG(5, (THIS_FILE, "pjsip_endpt_create_tsx()"));
-
- /* Request one pool for the transaction. Mutex is locked there. */
- pool = pjsip_endpt_create_pool(endpt, "ptsx%p",
- PJSIP_POOL_LEN_TSX, PJSIP_POOL_INC_TSX);
- if (pool == NULL) {
- return PJ_ENOMEM;
- }
-
- /* Create the transaction. */
- return pjsip_tsx_create(pool, endpt, p_tsx);
-}
-
-/*
- * Register the transaction to the endpoint.
- * This will put the transaction to the transaction hash table. Before calling
- * this function, the transaction must be INITIALIZED as either UAS or UAC, so
- * that the transaction key is built.
- */
-PJ_DEF(void) pjsip_endpt_register_tsx( pjsip_endpoint *endpt,
- pjsip_transaction *tsx)
-{
- PJ_LOG(5, (THIS_FILE, "pjsip_endpt_register_tsx(%s)", tsx->obj_name));
-
- pj_assert(tsx->transaction_key.slen != 0);
- //pj_assert(tsx->state != PJSIP_TSX_STATE_NULL);
-
- /* Lock hash table mutex. */
- pj_mutex_lock(endpt->tsx_table_mutex);
-
- /* Register the transaction to the hash table. */
- pj_hash_set( tsx->pool, endpt->tsx_table, tsx->transaction_key.ptr,
- tsx->transaction_key.slen, tsx);
-
- /* Unlock mutex. */
- pj_mutex_unlock(endpt->tsx_table_mutex);
-}
-
-/*
- * Find transaction by the key.
- */
-PJ_DEF(pjsip_transaction*) pjsip_endpt_find_tsx( pjsip_endpoint *endpt,
- const pj_str_t *key )
-{
- pjsip_transaction *tsx;
-
- PJ_LOG(5, (THIS_FILE, "pjsip_endpt_find_tsx()"));
-
- /* Start lock mutex in the endpoint. */
- pj_mutex_lock(endpt->tsx_table_mutex);
-
- /* Find the transaction in the hash table. */
- tsx = pj_hash_get( endpt->tsx_table, key->ptr, key->slen );
-
- /* Unlock mutex. */
- pj_mutex_unlock(endpt->tsx_table_mutex);
-
- return tsx;
-}
-
-/*
- * Create key.
- */
-static void rdata_create_key( pjsip_rx_data *rdata)
-{
- pjsip_role_e role;
- if (rdata->msg_info.msg->type == PJSIP_REQUEST_MSG) {
- role = PJSIP_ROLE_UAS;
- } else {
- role = PJSIP_ROLE_UAC;
- }
- pjsip_tsx_create_key(rdata->tp_info.pool, &rdata->endpt_info.key, role,
- &rdata->msg_info.cseq->method, rdata);
-}
-
-/*
* This is the callback that is called by the transport manager when it
* receives a message from the network.
*/
@@ -719,19 +558,17 @@ static void endpt_transport_callback( pjsip_endpoint *endpt,
pjsip_rx_data *rdata )
{
pjsip_msg *msg = rdata->msg_info.msg;
- pjsip_transaction *tsx;
- pj_bool_t a_new_transaction_just_been_created = PJ_FALSE;
PJ_LOG(5, (THIS_FILE, "endpt_transport_callback(rdata=%p)", rdata));
if (status != PJ_SUCCESS) {
- const char *src_addr = rdata->pkt_info.src_name;
- int port = rdata->pkt_info.src_port;
PJSIP_ENDPT_LOG_ERROR((endpt, "transport", status,
- "Src.addr=%s:%d, packet:--\n"
+ "Error processing packet from %s:%d, packet:--\n"
"%s\n"
- "-- end of packet. Error",
- src_addr, port, rdata->msg_info.msg_buf));
+ "-- end of packet.",
+ rdata->pkt_info.src_name,
+ rdata->pkt_info.src_port,
+ rdata->msg_info.msg_buf));
return;
}
@@ -740,7 +577,7 @@ static void endpt_transport_callback( pjsip_endpoint *endpt,
* Ref: RFC3261 Section 18.1.2 Receiving Response
*/
if (msg->type == PJSIP_RESPONSE_MSG) {
- const pj_str_t *addr_addr;
+ const pj_str_t *local_addr;
int port = rdata->msg_info.via->sent_by.port;
pj_bool_t mismatch = PJ_FALSE;
if (port == 0) {
@@ -748,8 +585,8 @@ static void endpt_transport_callback( pjsip_endpoint *endpt,
type = rdata->tp_info.transport->key.type;
port = pjsip_transport_get_default_port_for_type(type);
}
- addr_addr = &rdata->tp_info.transport->local_name.host;
- if (pj_strcmp(&rdata->msg_info.via->sent_by.host, addr_addr) != 0)
+ local_addr = &rdata->tp_info.transport->local_name.host;
+ if (pj_strcmp(&rdata->msg_info.via->sent_by.host, local_addr) != 0)
mismatch = PJ_TRUE;
else if (port != rdata->tp_info.transport->local_name.port) {
/* Port or address mismatch, we should discard response */
@@ -759,186 +596,71 @@ static void endpt_transport_callback( pjsip_endpoint *endpt,
* So we discard the response only if the port doesn't match
* both the port in sent-by and rport. We try to be lenient here!
*/
- if (rdata->msg_info.via->rport_param != rdata->tp_info.transport->local_name.port)
+ if (rdata->msg_info.via->rport_param !=
+ rdata->tp_info.transport->local_name.port)
mismatch = PJ_TRUE;
else {
- PJ_LOG(4,(THIS_FILE, "Response %p has mismatch port in sent-by"
- " but the rport parameter is correct",
- rdata));
+ PJ_LOG(4,(THIS_FILE, "Response %p from %s has mismatch port in "
+ "sent-by but the rport parameter is "
+ "correct",
+ rdata, rdata->pkt_info.src_name));
}
}
if (mismatch) {
- pjsip_event e;
-
- PJSIP_EVENT_INIT_DISCARD_MSG(e, rdata, PJSIP_EINVALIDVIA);
- endpt_do_event( endpt, &e );
+ PJ_TODO(ENDPT_REPORT_WHEN_DROPPING_MESSAGE);
+ PJ_LOG(4,(THIS_FILE, "Dropping response from %s:%d because sent-by"
+ " is mismatch",
+ rdata->pkt_info.src_name,
+ rdata->pkt_info.src_port));
return;
}
- }
-
- /* Create key for transaction lookup. */
- rdata_create_key( rdata);
-
- /* Find the transaction for the received message. */
- PJ_LOG(5, (THIS_FILE, "finding tsx with key=%.*s",
- rdata->endpt_info.key.slen, rdata->endpt_info.key.ptr));
-
- /* Start lock mutex in the endpoint. */
- pj_mutex_lock(endpt->tsx_table_mutex);
-
- /* Find the transaction in the hash table. */
- tsx = pj_hash_get( endpt->tsx_table, rdata->endpt_info.key.ptr, rdata->endpt_info.key.slen );
-
- /* Unlock mutex. */
- pj_mutex_unlock(endpt->tsx_table_mutex);
-
- /* If the transaction is not found... */
- if (tsx == NULL || tsx->state == PJSIP_TSX_STATE_TERMINATED) {
-
- /*
- * For response message, discard the message, except if the response is
- * an 2xx class response to INVITE, which in this case it must be
- * passed to TU to be acked.
- */
- if (msg->type == PJSIP_RESPONSE_MSG) {
-
- /* Inform TU about the 200 message, only if it's INVITE. */
- if (PJSIP_IS_STATUS_IN_CLASS(msg->line.status.code, 200) &&
- rdata->msg_info.cseq->method.id == PJSIP_INVITE_METHOD)
- {
- pjsip_event e;
-
- /* Should not happen for UA. Tsx theoritically lives until
- * all responses are absorbed.
- */
- pj_assert(0);
-
- PJSIP_EVENT_INIT_RX_200_MSG(e, rdata);
- endpt_do_event( endpt, &e );
-
- } else {
- /* Just discard the response, inform TU. */
- pjsip_event e;
-
- PJSIP_EVENT_INIT_DISCARD_MSG(e, rdata,
- PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_CALL_TSX_DOES_NOT_EXIST));
- endpt_do_event( endpt, &e );
- }
-
- /*
- * For non-ACK request message, create a new transaction.
- */
- } else if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) {
+ }
- pj_status_t status;
- /* Create transaction, mutex is locked there. */
- status = pjsip_endpt_create_tsx(endpt, &tsx);
- if (status != PJ_SUCCESS) {
- PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status,
- "Unable to create transaction"));
- return;
- }
+ /* Distribute to modules. */
+ pj_rwmutex_lock_read(endpt->mod_mutex);
- /* Initialize transaction as UAS. */
- pjsip_tsx_init_uas( tsx, rdata );
+ if (msg->type == PJSIP_REQUEST_MSG) {
+ pjsip_module *mod;
+ pj_bool_t handled = PJ_FALSE;
- /* Register transaction, mutex is locked there. */
- pjsip_endpt_register_tsx( endpt, tsx );
-
- a_new_transaction_just_been_created = PJ_TRUE;
+ mod = endpt->module_list.next;
+ while (mod != &endpt->module_list) {
+ if (mod->on_rx_request)
+ handled = (*mod->on_rx_request)(rdata);
+ if (handled)
+ break;
+ mod = mod->next;
}
- }
- /* If transaction is found (or newly created), pass the message.
- * Otherwise if it's an ACK request, pass directly to TU.
- */
- if (tsx && tsx->state != PJSIP_TSX_STATE_TERMINATED) {
- /* Dispatch message to transaction. */
- pjsip_tsx_on_rx_msg( tsx, rdata );
-
- } else if (rdata->msg_info.msg->line.req.method.id == PJSIP_ACK_METHOD) {
- /*
- * This is an ACK message, but the INVITE transaction could not
- * be found (possibly because the branch parameter in Via in ACK msg
- * is different than the branch in original INVITE). This happens with
- * SER!
- */
- pjsip_event event;
-
- PJSIP_EVENT_INIT_RX_ACK_MSG(event,rdata);
- endpt_do_event( endpt, &event );
- }
+ /* No module is able to handle the request. */
+ if (!handled) {
+ PJ_TODO(ENDPT_RESPOND_UNHANDLED_REQUEST);
+ PJ_LOG(4,(THIS_FILE, "Request from %s:%d was dropped/unhandled by"
+ " any modules"));
+ }
- /*
- * If a new request message has just been receieved, but no modules
- * seem to be able to handle the request message, then terminate the
- * transaction.
- *
- * Ideally for cases like "unsupported method", we should be able to
- * answer the request statelessly. But we can not do that since the
- * endpoint shoule be able to be used as both user agent and proxy stack,
- * and a proxy stack should be able to handle arbitrary methods.
- */
- if (a_new_transaction_just_been_created && tsx->status_code < 100) {
- /* Certainly no modules has sent any response message.
- * Check that any modules has attached a module data.
- */
- int i;
- for (i=0; i<PJSIP_MAX_MODULE; ++i) {
- if (tsx->module_data[i] != NULL) {
+ } else {
+ pjsip_module *mod;
+ pj_bool_t handled = PJ_FALSE;
+
+ mod = endpt->module_list.next;
+ while (mod != &endpt->module_list) {
+ if (mod->on_rx_response)
+ handled = (*mod->on_rx_response)(rdata);
+ if (handled)
break;
- }
+ mod = mod->next;
}
- if (i == PJSIP_MAX_MODULE) {
- /* No modules have attached itself to the transaction.
- * Terminate the transaction with 501/Not Implemented.
- */
- pjsip_tx_data *tdata;
- pj_status_t status;
-
- if (tsx->method.id == PJSIP_OPTIONS_METHOD) {
- status = pjsip_endpt_create_response(endpt, rdata, 200,
- &tdata);
- } else {
- status = pjsip_endpt_create_response(endpt, rdata,
- PJSIP_SC_METHOD_NOT_ALLOWED,
- &tdata);
- }
-
- if (status != PJ_SUCCESS) {
- PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status,
- "Unable to create response"));
- return;
- }
- if (endpt->allow_hdr) {
- pjsip_msg_add_hdr( tdata->msg,
- pjsip_hdr_shallow_clone(tdata->pool, endpt->allow_hdr));
- }
- pjsip_tsx_on_tx_msg( tsx, tdata );
-
- } else {
- /*
- * If a module has registered itself in the transaction but it
- * hasn't responded the request, chances are the module wouldn't
- * respond to the request at all. We terminate the request here
- * with 500/Internal Server Error, to be safe.
- */
- pjsip_tx_data *tdata;
- pj_status_t status;
-
- status = pjsip_endpt_create_response(endpt, rdata, 500, &tdata);
- if (status != PJ_SUCCESS) {
- PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status,
- "Unable to create response"));
- return;
- }
-
- pjsip_tsx_on_tx_msg(tsx, tdata);
+ if (!handled) {
+ PJ_LOG(4,(THIS_FILE, "Response from %s:%d was dropped/unhandled by"
+ " any modules"));
}
}
+
+ pj_rwmutex_unlock_read(endpt->mod_mutex);
}
/*
@@ -983,15 +705,15 @@ PJ_DEF(pj_ioqueue_t*) pjsip_endpt_get_ioqueue(pjsip_endpoint *endpt)
/*
* Find/create transport.
*/
-PJ_DEF(pj_status_t) pjsip_endpt_alloc_transport( pjsip_endpoint *endpt,
+PJ_DEF(pj_status_t) pjsip_endpt_acquire_transport(pjsip_endpoint *endpt,
pjsip_transport_type_e type,
- const pj_sockaddr *remote,
+ const pj_sockaddr_t *remote,
int addr_len,
- pjsip_transport **p_transport)
+ pjsip_transport **transport)
{
- PJ_LOG(5, (THIS_FILE, "pjsip_endpt_alloc_transport()"));
- return pjsip_tpmgr_alloc_transport( endpt->transport_mgr, type,
- remote, addr_len, p_transport);
+ PJ_LOG(5, (THIS_FILE, "pjsip_endpt_acquire_transport()"));
+ return pjsip_tpmgr_acquire_transport(endpt->transport_mgr, type,
+ remote, addr_len, transport);
}
@@ -1049,8 +771,6 @@ PJ_DEF(void) pjsip_endpt_log_error( pjsip_endpoint *endpt,
PJ_DEF(void) pjsip_endpt_dump( pjsip_endpoint *endpt, pj_bool_t detail )
{
#if PJ_LOG_MAX_LEVEL >= 3
- unsigned count;
-
PJ_LOG(5, (THIS_FILE, "pjsip_endpt_dump()"));
/* Lock mutex. */
@@ -1066,53 +786,6 @@ PJ_DEF(void) pjsip_endpt_dump( pjsip_endpoint *endpt, pj_bool_t detail )
pj_pool_get_capacity(endpt->pool),
pj_pool_get_used_size(endpt->pool)));
- /* Transaction tables. */
- count = pj_hash_count(endpt->tsx_table);
- PJ_LOG(3, (THIS_FILE, " Number of transactions: %u", count));
-
- if (count && detail) {
- pj_hash_iterator_t it_val;
- pj_hash_iterator_t *it;
- pj_time_val now;
-
- PJ_LOG(3, (THIS_FILE, " Dumping transaction tables:"));
-
- pj_gettimeofday(&now);
- it = pj_hash_first(endpt->tsx_table, &it_val);
-
- while (it != NULL) {
- int timeout_diff;
-
- /* Get the transaction. No need to lock transaction's mutex
- * since we already hold endpoint mutex, so that no transactions
- * will be deleted.
- */
- pjsip_transaction *tsx = pj_hash_this(endpt->tsx_table, it);
-
- const char *role = (tsx->role == PJSIP_ROLE_UAS ? "UAS" : "UAC");
-
- if (tsx->timeout_timer._timer_id != -1) {
- if (tsx->timeout_timer._timer_value.sec > now.sec) {
- timeout_diff = tsx->timeout_timer._timer_value.sec - now.sec;
- } else {
- timeout_diff = now.sec - tsx->timeout_timer._timer_value.sec;
- timeout_diff = 0 - timeout_diff;
- }
- } else {
- timeout_diff = -1;
- }
-
- PJ_LOG(3, (THIS_FILE, " %s %s %10.*s %.9u %s t=%ds",
- tsx->obj_name, role,
- tsx->method.name.slen, tsx->method.name.ptr,
- tsx->cseq,
- pjsip_tsx_state_str(tsx->state),
- timeout_diff));
-
- it = pj_hash_next(endpt->tsx_table, it);
- }
- }
-
/* Transports.
*/
pjsip_tpmgr_dump_transports( endpt->transport_mgr );