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

📄 sip_transport.c

📁 基于sip协议的网络电话源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* $Id: sip_transport.c 974 2007-02-19 01:13:53Z bennylp $ *//*  * Copyright (C) 2003-2007 Benny Prijono <benny@prijono.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  */#include <pjsip/sip_transport.h>#include <pjsip/sip_endpoint.h>#include <pjsip/sip_parser.h>#include <pjsip/sip_msg.h>#include <pjsip/sip_private.h>#include <pjsip/sip_errno.h>#include <pjsip/sip_module.h>#include <pj/except.h>#include <pj/os.h>#include <pj/log.h>#include <pj/ioqueue.h>#include <pj/hash.h>#include <pj/string.h>#include <pj/pool.h>#include <pj/assert.h>#include <pj/lock.h>#define THIS_FILE    "sip_transport.c"#if 0#   define TRACE_(x)	PJ_LOG(5,x)#else#   define TRACE_(x)#endif/* Prototype. */static pj_status_t mod_on_tx_msg(pjsip_tx_data *tdata);/* This module has sole purpose to print transmit data to contigous buffer * before actually transmitted to the wire.  */static pjsip_module mod_msg_print = {    NULL, NULL,				/* prev and next		    */    { "mod-msg-print", 13},		/* Name.			    */    -1,					/* Id				    */    PJSIP_MOD_PRIORITY_TRANSPORT_LAYER,	/* Priority			    */    NULL,				/* load()			    */    NULL,				/* start()			    */    NULL,				/* stop()			    */    NULL,				/* unload()			    */    NULL,				/* on_rx_request()		    */    NULL,				/* on_rx_response()		    */    &mod_on_tx_msg,			/* on_tx_request()		    */    &mod_on_tx_msg,			/* on_tx_response()		    */    NULL,				/* on_tsx_state()		    */};/* * Transport manager. */struct pjsip_tpmgr {    pj_hash_table_t *table;    pj_lock_t	    *lock;    pjsip_endpoint  *endpt;    pjsip_tpfactory  factory_list;#if defined(PJ_DEBUG) && PJ_DEBUG!=0    pj_atomic_t	    *tdata_counter;#endif    void           (*on_rx_msg)(pjsip_endpoint*, pj_status_t, pjsip_rx_data*);    pj_status_t	   (*on_tx_msg)(pjsip_endpoint*, pjsip_tx_data*);};/* Key for looking up hash table */struct transport_key{    pjsip_transport_type_e  type;    pj_sockaddr		    addr;};/***************************************************************************** * * GENERAL TRANSPORT (NAMES, TYPES, ETC.) * *****************************************************************************//* * Transport names. */struct{    pjsip_transport_type_e type;    pj_uint16_t		   port;    pj_str_t		   name;    unsigned		   flag;    char		   name_buf[16];} transport_names[16] = {    { PJSIP_TRANSPORT_UNSPECIFIED, 0, {"Unspecified", 11}, 0},    { PJSIP_TRANSPORT_UDP, 5060, {"UDP", 3}, PJSIP_TRANSPORT_DATAGRAM},    { PJSIP_TRANSPORT_TCP, 5060, {"TCP", 3}, PJSIP_TRANSPORT_RELIABLE},    { PJSIP_TRANSPORT_TLS, 5061, {"TLS", 3}, PJSIP_TRANSPORT_RELIABLE | PJSIP_TRANSPORT_SECURE},    { PJSIP_TRANSPORT_SCTP, 5060, {"SCTP", 4}, PJSIP_TRANSPORT_RELIABLE},    { PJSIP_TRANSPORT_LOOP, 15060, {"LOOP", 4}, PJSIP_TRANSPORT_RELIABLE},     { PJSIP_TRANSPORT_LOOP_DGRAM, 15060, {"LOOP-DGRAM", 10}, PJSIP_TRANSPORT_DATAGRAM},};/* * Register new transport type to PJSIP. */PJ_DECL(pj_status_t) pjsip_transport_register_type(unsigned tp_flag,						   const char *tp_name,						   int def_port,						   int *p_tp_type){    unsigned i;    PJ_ASSERT_RETURN(tp_flag && tp_name && def_port, PJ_EINVAL);    PJ_ASSERT_RETURN(pj_ansi_strlen(tp_name) < 			PJ_ARRAY_SIZE(transport_names[0].name_buf), 		     PJ_ENAMETOOLONG);    for (i=1; i<PJ_ARRAY_SIZE(transport_names); ++i) {	if (transport_names[i].type == 0)	    break;    }    if (i == PJ_ARRAY_SIZE(transport_names))	return PJ_ETOOMANY;    transport_names[i].type = (pjsip_transport_type_e)i;    transport_names[i].port = (pj_uint16_t)def_port;    pj_ansi_strcpy(transport_names[i].name_buf, tp_name);    transport_names[i].name = pj_str(transport_names[i].name_buf);    transport_names[i].flag = tp_flag;    if (p_tp_type)	*p_tp_type = i;    return PJ_SUCCESS;}/* * Get transport type from name. */PJ_DEF(pjsip_transport_type_e) pjsip_transport_get_type_from_name(const pj_str_t *name){    unsigned i;    /* Sanity check.      * Check that transport_names[] are indexed on transport type.      */    PJ_ASSERT_RETURN(transport_names[PJSIP_TRANSPORT_UDP].type ==		     PJSIP_TRANSPORT_UDP, PJSIP_TRANSPORT_UNSPECIFIED);    if (name->slen == 0)	return PJSIP_TRANSPORT_UNSPECIFIED;    /* Get transport type from name. */    for (i=0; i<PJ_ARRAY_SIZE(transport_names); ++i) {	if (pj_stricmp(name, &transport_names[i].name) == 0) {	    return transport_names[i].type;	}    }    pj_assert(!"Invalid transport name");    return PJSIP_TRANSPORT_UNSPECIFIED;}/* * Get the transport type for the specified flags. */PJ_DEF(pjsip_transport_type_e) pjsip_transport_get_type_from_flag(unsigned flag){    unsigned i;    /* Sanity check.      * Check that transport_names[] are indexed on transport type.      */    PJ_ASSERT_RETURN(transport_names[PJSIP_TRANSPORT_UDP].type ==		     PJSIP_TRANSPORT_UDP, PJSIP_TRANSPORT_UNSPECIFIED);    /* Get the transport type for the specified flags. */    for (i=0; i<PJ_ARRAY_SIZE(transport_names); ++i) {	if (transport_names[i].flag == flag) {	    return transport_names[i].type;	}    }    pj_assert(!"Invalid transport type");    return PJSIP_TRANSPORT_UNSPECIFIED;}PJ_DEF(unsigned)pjsip_transport_get_flag_from_type( pjsip_transport_type_e type ){    /* Sanity check.      * Check that transport_names[] are indexed on transport type.      */    PJ_ASSERT_RETURN(transport_names[PJSIP_TRANSPORT_UDP].type ==		     PJSIP_TRANSPORT_UDP, 0);    /* Check that argument is valid. */    PJ_ASSERT_RETURN(type < PJ_ARRAY_SIZE(transport_names), 0);    /* Return transport flag. */    return transport_names[type].flag;}/* * Get the default SIP port number for the specified type. */PJ_DEF(int) pjsip_transport_get_default_port_for_type(pjsip_transport_type_e type){    /* Sanity check.      * Check that transport_names[] are indexed on transport type.      */    PJ_ASSERT_RETURN(transport_names[PJSIP_TRANSPORT_UDP].type ==		     PJSIP_TRANSPORT_UDP, 0);    /* Check that argument is valid. */    PJ_ASSERT_RETURN(type < PJ_ARRAY_SIZE(transport_names), 5060);    /* Return the port. */    return transport_names[type].port;}/* * Get transport name. */PJ_DEF(const char*) pjsip_transport_get_type_name(pjsip_transport_type_e type){    /* Sanity check.      * Check that transport_names[] are indexed on transport type.      */    PJ_ASSERT_RETURN(transport_names[PJSIP_TRANSPORT_UDP].type ==		     PJSIP_TRANSPORT_UDP, "Unknown");    /* Check that argument is valid. */    PJ_ASSERT_RETURN(type < PJ_ARRAY_SIZE(transport_names), "Unknown");    /* Return the port. */    return transport_names[type].name.ptr;}/***************************************************************************** * * TRANSPORT SELECTOR * *****************************************************************************//* * Add transport/listener reference in the selector. */PJ_DEF(void) pjsip_tpselector_add_ref(pjsip_tpselector *sel){    if (sel->type == PJSIP_TPSELECTOR_TRANSPORT && sel->u.transport != NULL)	pjsip_transport_add_ref(sel->u.transport);    else if (sel->type == PJSIP_TPSELECTOR_LISTENER && sel->u.listener != NULL)	; /* Hmm.. looks like we don't have reference counter for listener */}/* * Decrement transport/listener reference in the selector. */PJ_DEF(void) pjsip_tpselector_dec_ref(pjsip_tpselector *sel){    if (sel->type == PJSIP_TPSELECTOR_TRANSPORT && sel->u.transport != NULL)	pjsip_transport_dec_ref(sel->u.transport);    else if (sel->type == PJSIP_TPSELECTOR_LISTENER && sel->u.listener != NULL)	; /* Hmm.. looks like we don't have reference counter for listener */}/***************************************************************************** * * TRANSMIT DATA BUFFER MANIPULATION. * *****************************************************************************//* * Create new transmit buffer. */PJ_DEF(pj_status_t) pjsip_tx_data_create( pjsip_tpmgr *mgr,					  pjsip_tx_data **p_tdata ){    pj_pool_t *pool;    pjsip_tx_data *tdata;    pj_status_t status;    PJ_ASSERT_RETURN(mgr && p_tdata, PJ_EINVAL);    pool = pjsip_endpt_create_pool( mgr->endpt, "tdta%p",				    PJSIP_POOL_LEN_TDATA,				    PJSIP_POOL_INC_TDATA );    if (!pool)	return PJ_ENOMEM;    tdata = pj_pool_zalloc(pool, sizeof(pjsip_tx_data));    tdata->pool = pool;    tdata->mgr = mgr;    pj_ansi_snprintf(tdata->obj_name, PJ_MAX_OBJ_NAME, "tdta%p", tdata);    status = pj_atomic_create(tdata->pool, 0, &tdata->ref_cnt);    if (status != PJ_SUCCESS) {	pjsip_endpt_release_pool( mgr->endpt, tdata->pool );	return status;    }        //status = pj_lock_create_simple_mutex(pool, "tdta%p", &tdata->lock);    status = pj_lock_create_null_mutex(pool, "tdta%p", &tdata->lock);    if (status != PJ_SUCCESS) {	pjsip_endpt_release_pool( mgr->endpt, tdata->pool );	return status;    }    pj_ioqueue_op_key_init(&tdata->op_key.key, sizeof(tdata->op_key));#if defined(PJ_DEBUG) && PJ_DEBUG!=0    pj_atomic_inc( tdata->mgr->tdata_counter );#endif    *p_tdata = tdata;    return PJ_SUCCESS;}/* * Add reference to tx buffer. */PJ_DEF(void) pjsip_tx_data_add_ref( pjsip_tx_data *tdata ){    pj_atomic_inc(tdata->ref_cnt);}/* * Decrease transport data reference, destroy it when the reference count * reaches zero. */PJ_DEF(pj_status_t) pjsip_tx_data_dec_ref( pjsip_tx_data *tdata ){    pj_assert( pj_atomic_get(tdata->ref_cnt) > 0);    if (pj_atomic_dec_and_get(tdata->ref_cnt) <= 0) {	PJ_LOG(5,(tdata->obj_name, "Destroying txdata %s",		  pjsip_tx_data_get_info(tdata)));	pjsip_tpselector_dec_ref(&tdata->tp_sel);#if defined(PJ_DEBUG) && PJ_DEBUG!=0	pj_atomic_dec( tdata->mgr->tdata_counter );#endif	pj_atomic_destroy( tdata->ref_cnt );	pj_lock_destroy( tdata->lock );	pjsip_endpt_release_pool( tdata->mgr->endpt, tdata->pool );	return PJSIP_EBUFDESTROYED;    } else {	return PJ_SUCCESS;    }}/* * Invalidate the content of the print buffer to force the message to be * re-printed when sent. */PJ_DEF(void) pjsip_tx_data_invalidate_msg( pjsip_tx_data *tdata ){    tdata->buf.cur = tdata->buf.start;    tdata->info = NULL;}PJ_DEF(pj_bool_t) pjsip_tx_data_is_valid( pjsip_tx_data *tdata ){    return tdata->buf.cur != tdata->buf.start;}static char *get_msg_info(pj_pool_t *pool, const char *obj_name,			  const pjsip_msg *msg){    char info_buf[128], *info;    const pjsip_cseq_hdr *cseq;    int len;    cseq = pjsip_msg_find_hdr(msg, PJSIP_H_CSEQ, NULL);    PJ_ASSERT_RETURN(cseq != NULL, "INVALID MSG");    if (msg->type == PJSIP_REQUEST_MSG) {	len = pj_ansi_snprintf(info_buf, sizeof(info_buf), 			       "Request msg %.*s/cseq=%d (%s)",			       (int)msg->line.req.method.name.slen,			       msg->line.req.method.name.ptr,			       cseq->cseq, obj_name);    } else {	len = pj_ansi_snprintf(info_buf, sizeof(info_buf),			       "Response msg %d/%.*s/cseq=%d (%s)",			       msg->line.status.code,			       (int)cseq->method.name.slen,			       cseq->method.name.ptr,			       cseq->cseq, obj_name);    }    if (len < 1 || len >= sizeof(info_buf)) {	return (char*)obj_name;    }    info = pj_pool_alloc(pool, len+1);    pj_memcpy(info, info_buf, len+1);    return info;}PJ_DEF(char*) pjsip_tx_data_get_info( pjsip_tx_data *tdata ){    if (tdata==NULL || tdata->msg==NULL)	return "NULL";    if (tdata->info)	return tdata->info;    pj_lock_acquire(tdata->lock);    tdata->info = get_msg_info(tdata->pool, tdata->obj_name, tdata->msg);    pj_lock_release(tdata->lock);    return tdata->info;}PJ_DEF(pj_status_t) pjsip_tx_data_set_transport(pjsip_tx_data *tdata,						const pjsip_tpselector *sel){    PJ_ASSERT_RETURN(tdata && sel, PJ_EINVAL);    pj_lock_acquire(tdata->lock);    pjsip_tpselector_dec_ref(&tdata->tp_sel);    pj_memcpy(&tdata->tp_sel, sel, sizeof(*sel));    pjsip_tpselector_add_ref(&tdata->tp_sel);    pj_lock_release(tdata->lock);    return PJ_SUCCESS;}PJ_DEF(char*) pjsip_rx_data_get_info(pjsip_rx_data *rdata){    char obj_name[PJ_MAX_OBJ_NAME];    PJ_ASSERT_RETURN(rdata->msg_info.msg, "INVALID MSG");    if (rdata->msg_info.info)	return rdata->msg_info.info;    pj_ansi_strcpy(obj_name, "rdata");    pj_ansi_snprintf(obj_name+5, sizeof(obj_name)-5, "%p", rdata);    rdata->msg_info.info = get_msg_info(rdata->tp_info.pool, obj_name,					rdata->msg_info.msg);    return rdata->msg_info.info;}/***************************************************************************** * * TRANSPORT KEY * *****************************************************************************//***************************************************************************** * * TRANSPORT * *****************************************************************************/static void transport_send_callback(pjsip_transport *transport,				    void *token,

⌨️ 快捷键说明

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