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

📄 sip_reg.c

📁 基于sip协议的网络电话源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: sip_reg.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-ua/sip_regc.h>#include <pjsip/sip_endpoint.h>#include <pjsip/sip_parser.h>#include <pjsip/sip_module.h>#include <pjsip/sip_transaction.h>#include <pjsip/sip_event.h>#include <pjsip/sip_util.h>#include <pjsip/sip_auth_msg.h>#include <pjsip/sip_errno.h>#include <pj/assert.h>#include <pj/guid.h>#include <pj/os.h>#include <pj/pool.h>#include <pj/log.h>#include <pj/rand.h>#include <pj/string.h>#define REFRESH_TIMER		1#define DELAY_BEFORE_REFRESH	5#define THIS_FILE		"sip_regc.c"/* Outgoing transaction timeout when server sends 100 but never replies * with final response. Value is in MILISECONDS! */#define REGC_TSX_TIMEOUT	33000/** * SIP client registration structure. */struct pjsip_regc{    pj_pool_t			*pool;    pjsip_endpoint		*endpt;    pj_bool_t			 _delete_flag;    pj_bool_t			 has_tsx;    pj_int32_t			 busy;    void			*token;    pjsip_regc_cb		*cb;    pj_str_t			 str_srv_url;    pjsip_uri			*srv_url;    pjsip_cid_hdr		*cid_hdr;    pjsip_cseq_hdr		*cseq_hdr;    pj_str_t			 from_uri;    pjsip_from_hdr		*from_hdr;    pjsip_to_hdr		*to_hdr;    char			*contact_buf;    pjsip_generic_string_hdr	*contact_hdr;    pjsip_expires_hdr		*expires_hdr;    pjsip_contact_hdr		*unreg_contact_hdr;    pjsip_expires_hdr		*unreg_expires_hdr;    pj_uint32_t			 expires;    pjsip_route_hdr		 route_set;    pjsip_hdr			 hdr_list;    /* Authorization sessions. */    pjsip_auth_clt_sess		 auth_sess;    /* Auto refresh registration. */    pj_bool_t			 auto_reg;    pj_time_val			 last_reg;    pj_time_val			 next_reg;    pj_timer_entry		 timer;    /* Transport selector */    pjsip_tpselector		 tp_sel;};PJ_DEF(pj_status_t) pjsip_regc_create( pjsip_endpoint *endpt, void *token,				       pjsip_regc_cb *cb,				       pjsip_regc **p_regc){    pj_pool_t *pool;    pjsip_regc *regc;    pj_status_t status;    /* Verify arguments. */    PJ_ASSERT_RETURN(endpt && cb && p_regc, PJ_EINVAL);    pool = pjsip_endpt_create_pool(endpt, "regc%p", 1024, 1024);    PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM);    regc = pj_pool_zalloc(pool, sizeof(struct pjsip_regc));    regc->pool = pool;    regc->endpt = endpt;    regc->token = token;    regc->cb = cb;    regc->contact_buf = pj_pool_alloc(pool, PJSIP_REGC_CONTACT_BUF_SIZE);    regc->expires = PJSIP_REGC_EXPIRATION_NOT_SPECIFIED;    status = pjsip_auth_clt_init(&regc->auth_sess, endpt, regc->pool, 0);    if (status != PJ_SUCCESS)	return status;    pj_list_init(&regc->route_set);    pj_list_init(&regc->hdr_list);    /* Done */    *p_regc = regc;    return PJ_SUCCESS;}PJ_DEF(pj_status_t) pjsip_regc_destroy(pjsip_regc *regc){    PJ_ASSERT_RETURN(regc, PJ_EINVAL);    if (regc->has_tsx || regc->busy) {	regc->_delete_flag = 1;	regc->cb = NULL;    } else {	pjsip_tpselector_dec_ref(&regc->tp_sel);	pjsip_endpt_release_pool(regc->endpt, regc->pool);    }    return PJ_SUCCESS;}PJ_DEF(pj_status_t) pjsip_regc_get_info( pjsip_regc *regc,					 pjsip_regc_info *info ){    PJ_ASSERT_RETURN(regc && info, PJ_EINVAL);    info->server_uri = regc->str_srv_url;    info->client_uri = regc->from_uri;    info->is_busy = (regc->busy || regc->has_tsx);    info->auto_reg = regc->auto_reg;    info->interval = regc->expires;        if (regc->has_tsx)	info->next_reg = 0;    else if (regc->auto_reg == 0)	info->next_reg = 0;    else if (regc->expires < 0)	info->next_reg = regc->expires;    else {	pj_time_val now, next_reg;	next_reg = regc->next_reg;	pj_gettimeofday(&now);	PJ_TIME_VAL_SUB(next_reg, now);	info->next_reg = next_reg.sec;    }    return PJ_SUCCESS;}PJ_DEF(pj_pool_t*) pjsip_regc_get_pool(pjsip_regc *regc){    return regc->pool;}static void set_expires( pjsip_regc *regc, pj_uint32_t expires){    if (expires != regc->expires) {	regc->expires_hdr = pjsip_expires_hdr_create(regc->pool, expires);    } else {	regc->expires_hdr = NULL;    }}static pj_status_t set_contact( pjsip_regc *regc,			        int contact_cnt,				const pj_str_t contact[] ){    int i;    char *s;    const pj_str_t contact_STR = { "Contact", 7};    /* Concatenate contacts. */    for (i=0, s=regc->contact_buf; i<contact_cnt; ++i) {	if ((s-regc->contact_buf) + contact[i].slen + 2 > PJSIP_REGC_CONTACT_BUF_SIZE) {	    return PJSIP_EURITOOLONG;	}	pj_memcpy(s, contact[i].ptr, contact[i].slen);	s += contact[i].slen;	if (i != contact_cnt - 1) {	    *s++ = ',';	    *s++ = ' ';	}    }    /* Set "Contact" header. */    regc->contact_hdr = pjsip_generic_string_hdr_create(regc->pool, 							&contact_STR,							NULL);    regc->contact_hdr->hvalue.ptr = regc->contact_buf;    regc->contact_hdr->hvalue.slen = (s - regc->contact_buf);    return PJ_SUCCESS;}PJ_DEF(pj_status_t) pjsip_regc_init( pjsip_regc *regc,				     const pj_str_t *srv_url,				     const pj_str_t *from_url,				     const pj_str_t *to_url,				     int contact_cnt,				     const pj_str_t contact[],				     pj_uint32_t expires){    pj_str_t tmp;    pj_status_t status;    PJ_ASSERT_RETURN(regc && srv_url && from_url && to_url && 		     contact_cnt && contact && expires, PJ_EINVAL);    /* Copy server URL. */    pj_strdup_with_null(regc->pool, &regc->str_srv_url, srv_url);    /* Set server URL. */    tmp = regc->str_srv_url;    regc->srv_url = pjsip_parse_uri( regc->pool, tmp.ptr, tmp.slen, 0);    if (regc->srv_url == NULL) {	return PJSIP_EINVALIDURI;    }    /* Set "From" header. */    pj_strdup_with_null(regc->pool, &regc->from_uri, from_url);    tmp = regc->from_uri;    regc->from_hdr = pjsip_from_hdr_create(regc->pool);    regc->from_hdr->uri = pjsip_parse_uri(regc->pool, tmp.ptr, tmp.slen, 					  PJSIP_PARSE_URI_AS_NAMEADDR);    if (!regc->from_hdr->uri) {	PJ_LOG(4,(THIS_FILE, "regc: invalid source URI %.*s", 		  from_url->slen, from_url->ptr));	return PJSIP_EINVALIDURI;    }    /* Set "To" header. */    pj_strdup_with_null(regc->pool, &tmp, to_url);    regc->to_hdr = pjsip_to_hdr_create(regc->pool);    regc->to_hdr->uri = pjsip_parse_uri(regc->pool, tmp.ptr, tmp.slen, 					PJSIP_PARSE_URI_AS_NAMEADDR);    if (!regc->to_hdr->uri) {	PJ_LOG(4,(THIS_FILE, "regc: invalid target URI %.*s", to_url->slen, to_url->ptr));	return PJSIP_EINVALIDURI;    }    /* Set "Contact" header. */    status = set_contact( regc, contact_cnt, contact);    if (status != PJ_SUCCESS)	return status;    /* Set "Expires" header, if required. */    set_expires( regc, expires);    /* Set "Call-ID" header. */    regc->cid_hdr = pjsip_cid_hdr_create(regc->pool);    pj_create_unique_string(regc->pool, &regc->cid_hdr->id);    /* Set "CSeq" header. */    regc->cseq_hdr = pjsip_cseq_hdr_create(regc->pool);    regc->cseq_hdr->cseq = pj_rand() % 0xFFFF;    pjsip_method_set( &regc->cseq_hdr->method, PJSIP_REGISTER_METHOD);    /* Create "Contact" header used in unregistration. */    regc->unreg_contact_hdr = pjsip_contact_hdr_create(regc->pool);    regc->unreg_contact_hdr->star = 1;    /* Create "Expires" header used in unregistration. */    regc->unreg_expires_hdr = pjsip_expires_hdr_create( regc->pool, 0);    /* Done. */    return PJ_SUCCESS;}PJ_DEF(pj_status_t) pjsip_regc_set_credentials( pjsip_regc *regc,						int count,						const pjsip_cred_info cred[] ){    PJ_ASSERT_RETURN(regc && count && cred, PJ_EINVAL);    return pjsip_auth_clt_set_credentials(&regc->auth_sess, count, cred);}PJ_DEF(pj_status_t) pjsip_regc_set_route_set( pjsip_regc *regc,					      const pjsip_route_hdr *route_set){    const pjsip_route_hdr *chdr;    PJ_ASSERT_RETURN(regc && route_set, PJ_EINVAL);    pj_list_init(&regc->route_set);    chdr = route_set->next;    while (chdr != route_set) {	pj_list_push_back(&regc->route_set, pjsip_hdr_clone(regc->pool, chdr));	chdr = chdr->next;    }    return PJ_SUCCESS;}/* * Bind client registration to a specific transport/listener.  */PJ_DEF(pj_status_t) pjsip_regc_set_transport( pjsip_regc *regc,					      const pjsip_tpselector *sel){    PJ_ASSERT_RETURN(regc && sel, PJ_EINVAL);    pjsip_tpselector_dec_ref(&regc->tp_sel);    pj_memcpy(&regc->tp_sel, sel, sizeof(*sel));    pjsip_tpselector_add_ref(&regc->tp_sel);    return PJ_SUCCESS;}PJ_DEF(pj_status_t) pjsip_regc_add_headers( pjsip_regc *regc,					    const pjsip_hdr *hdr_list){    const pjsip_hdr *hdr;    PJ_ASSERT_RETURN(regc && hdr_list, PJ_EINVAL);    //This is "add" operation, so don't remove headers.    //pj_list_init(&regc->hdr_list);    hdr = hdr_list->next;    while (hdr != hdr_list) {	pj_list_push_back(&regc->hdr_list, pjsip_hdr_clone(regc->pool, hdr));	hdr = hdr->next;    }    return PJ_SUCCESS;}static pj_status_t create_request(pjsip_regc *regc, 				  pjsip_tx_data **p_tdata){    pj_status_t status;    pjsip_tx_data *tdata;    PJ_ASSERT_RETURN(regc && p_tdata, PJ_EINVAL);    /* Create the request. */    status = pjsip_endpt_create_request_from_hdr( regc->endpt, 						  &pjsip_register_method,						  regc->srv_url,						  regc->from_hdr,						  regc->to_hdr,						  NULL,						  regc->cid_hdr,						  regc->cseq_hdr->cseq,						  NULL,						  &tdata);    if (status != PJ_SUCCESS)	return status;    /* Add cached authorization headers. */    pjsip_auth_clt_init_req( &regc->auth_sess, tdata );    /* Add Route headers from route set, ideally after Via header */

⌨️ 快捷键说明

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