⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sip_transaction.c

📁 基于sip协议的网络电话源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    /*     * Register transaction layer module to endpoint.     */    status = pjsip_endpt_register_module( endpt, &mod_tsx_layer.mod );    if (status != PJ_SUCCESS) {	pj_mutex_destroy(mod_tsx_layer.mutex);	pjsip_endpt_release_pool(endpt, pool);	return status;    }    /* Register mod_stateful_util module (sip_util_statefull.c) */    status = pjsip_endpt_register_module(endpt, &mod_stateful_util);    if (status != PJ_SUCCESS) {	return status;    }    return PJ_SUCCESS;}/* * Get the instance of transaction layer module. */PJ_DEF(pjsip_module*) pjsip_tsx_layer_instance(void){    return &mod_tsx_layer.mod;}/* * Unregister and destroy transaction layer module. */PJ_DEF(pj_status_t) pjsip_tsx_layer_destroy(void){    /* Are we registered? */    PJ_ASSERT_RETURN(mod_tsx_layer.endpt!=NULL, PJ_EINVALIDOP);    /* Unregister from endpoint.      * Clean-ups will be done in the unload() module callback.     */    return pjsip_endpt_unregister_module( mod_tsx_layer.endpt, 					  &mod_tsx_layer.mod);}/* * Register the transaction to the hash table. */static pj_status_t mod_tsx_layer_register_tsx( pjsip_transaction *tsx){    pj_assert(tsx->transaction_key.slen != 0);    /* Lock hash table mutex. */    pj_mutex_lock(mod_tsx_layer.mutex);    /* Check if no transaction with the same key exists.      * Do not use PJ_ASSERT_RETURN since it evaluates the expression     * twice!     */    pj_assert(pj_hash_get( mod_tsx_layer.htable, 			   &tsx->transaction_key.ptr,			   tsx->transaction_key.slen, 			   NULL) == NULL);    TSX_TRACE_((THIS_FILE, 		"Transaction %p registered with hkey=0x%p and key=%.*s",		tsx, tsx->hashed_key, tsx->transaction_key.slen,		tsx->transaction_key.ptr));    /* Register the transaction to the hash table. */#ifdef PRECALC_HASH    pj_hash_set( tsx->pool, mod_tsx_layer.htable, tsx->transaction_key.ptr,    		 tsx->transaction_key.slen, tsx->hashed_key, tsx);#else    pj_hash_set( tsx->pool, mod_tsx_layer.htable, tsx->transaction_key.ptr,    		 tsx->transaction_key.slen, 0, tsx);#endif    /* Unlock mutex. */    pj_mutex_unlock(mod_tsx_layer.mutex);    return PJ_SUCCESS;}/* * Unregister the transaction from the hash table. */static void mod_tsx_layer_unregister_tsx( pjsip_transaction *tsx){    pj_assert(tsx->transaction_key.slen != 0);    //pj_assert(tsx->state != PJSIP_TSX_STATE_NULL);    /* Lock hash table mutex. */    pj_mutex_lock(mod_tsx_layer.mutex);    /* Register the transaction to the hash table. */#ifdef PRECALC_HASH    pj_hash_set( NULL, mod_tsx_layer.htable, tsx->transaction_key.ptr,    		 tsx->transaction_key.slen, tsx->hashed_key, NULL);#else    pj_hash_set( NULL, mod_tsx_layer.htable, tsx->transaction_key.ptr,    		 tsx->transaction_key.slen, 0, NULL);#endif    TSX_TRACE_((THIS_FILE, 		"Transaction %p unregistered, hkey=0x%p and key=%.*s",		tsx, tsx->hashed_key, tsx->transaction_key.slen,		tsx->transaction_key.ptr));    /* Unlock mutex. */    pj_mutex_unlock(mod_tsx_layer.mutex);}/* * Find a transaction. */PJ_DEF(pjsip_transaction*) pjsip_tsx_layer_find_tsx( const pj_str_t *key,						     pj_bool_t lock ){    pjsip_transaction *tsx;    pj_uint32_t hval = 0;    pj_mutex_lock(mod_tsx_layer.mutex);    tsx = pj_hash_get( mod_tsx_layer.htable, key->ptr, key->slen, &hval );    pj_mutex_unlock(mod_tsx_layer.mutex);    TSX_TRACE_((THIS_FILE, 		"Finding tsx with hkey=0x%p and key=%.*s: found %p",		hval, key->slen, key->ptr, tsx));    /* Race condition!     * Transaction may gets deleted before we have chance to lock it.     */    PJ_TODO(FIX_RACE_CONDITION_HERE);    if (tsx && lock)	pj_mutex_lock(tsx->mutex);    return tsx;}/* This module callback is called when module is being loaded by * endpoint. It does nothing for this module. */static pj_status_t mod_tsx_layer_load(pjsip_endpoint *endpt){    PJ_UNUSED_ARG(endpt);    return PJ_SUCCESS;}/* This module callback is called when module is being started by * endpoint. It does nothing for this module. */static pj_status_t mod_tsx_layer_start(void){    return PJ_SUCCESS;}/* This module callback is called when module is being stopped by * endpoint.  */static pj_status_t mod_tsx_layer_stop(void){    pj_hash_iterator_t it_buf, *it;    PJ_LOG(4,(THIS_FILE, "Stopping transaction layer module"));    pj_mutex_lock(mod_tsx_layer.mutex);    /* Destroy all transactions. */    it = pj_hash_first(mod_tsx_layer.htable, &it_buf);    while (it) {	pjsip_transaction *tsx = pj_hash_this(mod_tsx_layer.htable, it);	pj_hash_iterator_t *next = pj_hash_next(mod_tsx_layer.htable, it);	if (tsx) {	    mod_tsx_layer_unregister_tsx(tsx);	    tsx_destroy(tsx);	}	it = next;    }    pj_mutex_unlock(mod_tsx_layer.mutex);    return PJ_SUCCESS;}/* This module callback is called when module is being unloaded by * endpoint. */static pj_status_t mod_tsx_layer_unload(void){    /* Only self destroy when there's no transaction in the table.     * Transaction may refuse to destroy when it has pending     * transmission. If we destroy the module now, application will     * crash when the pending transaction finally got error response     * from transport and when it tries to unregister itself.     */    if (pj_hash_count(mod_tsx_layer.htable) != 0)	return PJ_EBUSY;    /* Destroy mutex. */    pj_mutex_destroy(mod_tsx_layer.mutex);    /* Release pool. */    pjsip_endpt_release_pool(mod_tsx_layer.endpt, mod_tsx_layer.pool);    /* Free TLS */    pj_thread_local_free(pjsip_tsx_lock_tls_id);    /* Mark as unregistered. */    mod_tsx_layer.endpt = NULL;    PJ_LOG(4,(THIS_FILE, "Transaction layer module destroyed"));    return PJ_SUCCESS;}/* This module callback is called when endpoint has received an * incoming request message. */static pj_bool_t mod_tsx_layer_on_rx_request(pjsip_rx_data *rdata){    pj_str_t key;    pj_uint32_t hval = 0;    pjsip_transaction *tsx;    pjsip_tsx_create_key(rdata->tp_info.pool, &key, PJSIP_ROLE_UAS,			 &rdata->msg_info.cseq->method, rdata);    /* Find transaction. */    pj_mutex_lock( mod_tsx_layer.mutex );    tsx = pj_hash_get( mod_tsx_layer.htable, key.ptr, key.slen, &hval );    TSX_TRACE_((THIS_FILE, 		"Finding tsx for request, hkey=0x%p and key=%.*s, found %p",		hval, key.slen, key.ptr, tsx));    if (tsx == NULL || tsx->state == PJSIP_TSX_STATE_TERMINATED) {	/* Transaction not found.	 * Reject the request so that endpoint passes the request to	 * upper layer modules.	 */	pj_mutex_unlock( mod_tsx_layer.mutex);	return PJ_FALSE;    }    /* Unlock hash table. */    pj_mutex_unlock( mod_tsx_layer.mutex );    /* Race condition!     * Transaction may gets deleted before we have chance to lock it     * in pjsip_tsx_recv_msg().     */    PJ_TODO(FIX_RACE_CONDITION_HERE);    /* Pass the message to the transaction. */    pjsip_tsx_recv_msg(tsx, rdata );    return PJ_TRUE;}/* This module callback is called when endpoint has received an * incoming response message. */static pj_bool_t mod_tsx_layer_on_rx_response(pjsip_rx_data *rdata){    pj_str_t key;    pj_uint32_t hval = 0;    pjsip_transaction *tsx;    pjsip_tsx_create_key(rdata->tp_info.pool, &key, PJSIP_ROLE_UAC,			 &rdata->msg_info.cseq->method, rdata);    /* Find transaction. */    pj_mutex_lock( mod_tsx_layer.mutex );    tsx = pj_hash_get( mod_tsx_layer.htable, key.ptr, key.slen, &hval );    TSX_TRACE_((THIS_FILE, 		"Finding tsx for response, hkey=0x%p and key=%.*s, found %p",		hval, key.slen, key.ptr, tsx));    if (tsx == NULL || tsx->state == PJSIP_TSX_STATE_TERMINATED) {	/* Transaction not found.	 * Reject the request so that endpoint passes the request to	 * upper layer modules.	 */	pj_mutex_unlock( mod_tsx_layer.mutex);	return PJ_FALSE;    }    /* Unlock hash table. */    pj_mutex_unlock( mod_tsx_layer.mutex );    /* Race condition!     * Transaction may gets deleted before we have chance to lock it     * in pjsip_tsx_recv_msg().     */    PJ_TODO(FIX_RACE_CONDITION_HERE);    /* Pass the message to the transaction. */    pjsip_tsx_recv_msg(tsx, rdata );    return PJ_TRUE;}/* * Get transaction instance in the rdata. */PJ_DEF(pjsip_transaction*) pjsip_rdata_get_tsx( pjsip_rx_data *rdata ){    return rdata->endpt_info.mod_data[mod_tsx_layer.mod.id];}/* * Dump transaction layer. */PJ_DEF(void) pjsip_tsx_layer_dump(pj_bool_t detail){#if PJ_LOG_MAX_LEVEL >= 3    pj_hash_iterator_t itbuf, *it;    /* Lock mutex. */    pj_mutex_lock(mod_tsx_layer.mutex);    PJ_LOG(3, (THIS_FILE, "Dumping transaction table:"));    PJ_LOG(3, (THIS_FILE, " Total %d transactions", 			  pj_hash_count(mod_tsx_layer.htable)));    if (detail) {	it = pj_hash_first(mod_tsx_layer.htable, &itbuf);	if (it == NULL) {	    PJ_LOG(3, (THIS_FILE, " - none - "));	} else {	    while (it != NULL) {		pjsip_transaction *tsx = pj_hash_this(mod_tsx_layer.htable,it);		PJ_LOG(3, (THIS_FILE, " %s %s|%d|%s",			   tsx->obj_name,			   (tsx->last_tx? 				pjsip_tx_data_get_info(tsx->last_tx): 				"none"),			   tsx->status_code,			   pjsip_tsx_state_str(tsx->state)));		it = pj_hash_next(mod_tsx_layer.htable, it);	    }	}    }    /* Unlock mutex. */    pj_mutex_unlock(mod_tsx_layer.mutex);#endif}/***************************************************************************** ** ** Transaction ** ***************************************************************************** **//* * Lock transaction and set the value of Thread Local Storage. */static void lock_tsx(pjsip_transaction *tsx, struct tsx_lock_data *lck){    struct tsx_lock_data *prev_data;    pj_mutex_lock(tsx->mutex);    prev_data = (struct tsx_lock_data *)                     pj_thread_local_get(pjsip_tsx_lock_tls_id);    lck->prev = prev_data;    lck->tsx = tsx;    lck->is_alive = 1;    pj_thread_local_set(pjsip_tsx_lock_tls_id, lck);}/* * Unlock transaction. * This will selectively unlock the mutex ONLY IF the transaction has not been  * destroyed. The function knows whether the transaction has been destroyed * because when transaction is destroyed the is_alive flag for the transaction * will be set to zero. */static pj_status_t unlock_tsx( pjsip_transaction *tsx,                                struct tsx_lock_data *lck){    pj_assert( (void*)pj_thread_local_get(pjsip_tsx_lock_tls_id) == lck);    pj_assert( lck->tsx == tsx );    pj_thread_local_set(pjsip_tsx_lock_tls_id, lck->prev);    if (lck->is_alive)	pj_mutex_unlock(tsx->mutex);    return lck->is_alive ? PJ_SUCCESS : PJSIP_ETSXDESTROYED;}/* Create and initialize basic transaction structure. * This function is called by both UAC and UAS creation. */static pj_status_t tsx_create( pjsip_module *tsx_user,			       pjsip_transaction **p_tsx){    pj_pool_t *pool;    pjsip_transaction *tsx;    pj_status_t status;    pool = pjsip_endpt_create_pool( mod_tsx_layer.endpt, "tsx", 				    PJSIP_POOL_TSX_LEN, PJSIP_POOL_TSX_INC );    if (!pool)	return PJ_ENOMEM;    tsx = pj_pool_zalloc(pool, sizeof(pjsip_transaction));    tsx->pool = pool;    tsx->tsx_user = tsx_user;    tsx->endpt = mod_tsx_layer.endpt;    pj_ansi_snprintf(tsx->obj_name, sizeof(tsx->obj_name), 		     "tsx%p", tsx);    tsx->handle_200resp = 1;    tsx->retransmit_timer.id = TSX_TIMER_RETRANSMISSION;    tsx->retransmit_timer._timer_id = -1;    tsx->retransmit_timer.user_data = tsx;    tsx->retransmit_timer.cb = &tsx_timer_callback;    tsx->timeout_timer.id = TSX_TIMER_TIMEOUT;    tsx->timeout_timer._timer_id = -1;    tsx->timeout_timer.user_data = tsx;    tsx->timeout_timer.cb = &tsx_timer_callback;        status = pj_mutex_create_recursive(pool, tsx->obj_name, &tsx->mutex);    if (status != PJ_SUCCESS) {	pjsip_endpt_release_pool(mod_tsx_layer.endpt, pool);	return status;    }    *p_tsx = tsx;    return PJ_SUCCESS;}/* Destroy transaction. */static pj_status_t tsx_destroy( pjsip_transaction *tsx ){    struct tsx_lock_data *lck;    /* Decrement transport reference counter. */    if (tsx->transport) {	pjsip_transport_dec_ref( tsx->transport );	tsx->transport = NULL;    }    /* Decrement reference counter in transport selector */    pjsip_tpselector_dec_ref(&tsx->tp_sel);    /* Free last transmitted message. */    if (tsx->last_tx) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -