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

📄 pjsua_acc.c

📁 基于sip协议的网络电话源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: pjsua_acc.c 1122 2007-04-02 11:22:49Z 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 <pjsua-lib/pjsua.h>#include <pjsua-lib/pjsua_internal.h>#define THIS_FILE		"pjsua_acc.c"/* * Get number of current accounts. */PJ_DEF(unsigned) pjsua_acc_get_count(void){    return pjsua_var.acc_cnt;}/* * Check if the specified account ID is valid. */PJ_DEF(pj_bool_t) pjsua_acc_is_valid(pjsua_acc_id acc_id){    return acc_id>=0 && acc_id<PJ_ARRAY_SIZE(pjsua_var.acc) &&	   pjsua_var.acc[acc_id].valid;}/* * Set default account */PJ_DEF(pj_status_t) pjsua_acc_set_default(pjsua_acc_id acc_id){    pjsua_var.default_acc = acc_id;    return PJ_SUCCESS;}/* * Get default account. */PJ_DEF(pjsua_acc_id) pjsua_acc_get_default(void){    return pjsua_var.default_acc;}/* * Copy account configuration. */static void copy_acc_config(pj_pool_t *pool,			    pjsua_acc_config *dst,			    const pjsua_acc_config *src){    unsigned i;    pj_memcpy(dst, src, sizeof(pjsua_acc_config));    pj_strdup_with_null(pool, &dst->id, &src->id);    pj_strdup_with_null(pool, &dst->reg_uri, &src->reg_uri);    pj_strdup_with_null(pool, &dst->force_contact, &src->force_contact);    dst->proxy_cnt = src->proxy_cnt;    for (i=0; i<src->proxy_cnt; ++i)	pj_strdup_with_null(pool, &dst->proxy[i], &src->proxy[i]);    dst->reg_timeout = src->reg_timeout;    dst->cred_count = src->cred_count;    for (i=0; i<src->cred_count; ++i) {	pjsip_cred_dup(pool, &dst->cred_info[i], &src->cred_info[i]);    }}/* * Initialize a new account (after configuration is set). */static pj_status_t initialize_acc(unsigned acc_id){    pjsua_acc_config *acc_cfg = &pjsua_var.acc[acc_id].cfg;    pjsua_acc *acc = &pjsua_var.acc[acc_id];    pjsip_name_addr *name_addr;    pjsip_sip_uri *sip_uri, *sip_reg_uri;    pj_status_t status;    unsigned i;    /* Need to parse local_uri to get the elements: */    name_addr = (pjsip_name_addr*)		    pjsip_parse_uri(pjsua_var.pool, acc_cfg->id.ptr,				    acc_cfg->id.slen, 				    PJSIP_PARSE_URI_AS_NAMEADDR);    if (name_addr == NULL) {	pjsua_perror(THIS_FILE, "Invalid local URI", 		     PJSIP_EINVALIDURI);	return PJSIP_EINVALIDURI;    }    /* Local URI MUST be a SIP or SIPS: */    if (!PJSIP_URI_SCHEME_IS_SIP(name_addr) && 	!PJSIP_URI_SCHEME_IS_SIPS(name_addr))     {	pjsua_perror(THIS_FILE, "Invalid local URI", 		     PJSIP_EINVALIDSCHEME);	return PJSIP_EINVALIDSCHEME;    }    /* Get the SIP URI object: */    sip_uri = (pjsip_sip_uri*) pjsip_uri_get_uri(name_addr);    /* Parse registrar URI, if any */    if (acc_cfg->reg_uri.slen) {	pjsip_uri *reg_uri;	reg_uri = pjsip_parse_uri(pjsua_var.pool, acc_cfg->reg_uri.ptr,				  acc_cfg->reg_uri.slen, 0);	if (reg_uri == NULL) {	    pjsua_perror(THIS_FILE, "Invalid registrar URI", 			 PJSIP_EINVALIDURI);	    return PJSIP_EINVALIDURI;	}	/* Registrar URI MUST be a SIP or SIPS: */	if (!PJSIP_URI_SCHEME_IS_SIP(reg_uri) && 	    !PJSIP_URI_SCHEME_IS_SIPS(reg_uri)) 	{	    pjsua_perror(THIS_FILE, "Invalid registar URI", 			 PJSIP_EINVALIDSCHEME);	    return PJSIP_EINVALIDSCHEME;	}	sip_reg_uri = (pjsip_sip_uri*) pjsip_uri_get_uri(reg_uri);    } else {	sip_reg_uri = NULL;    }    /* Save the user and domain part. These will be used when finding an      * account for incoming requests.     */    acc->display = name_addr->display;    acc->user_part = sip_uri->user;    acc->srv_domain = sip_uri->host;    acc->srv_port = 0;    if (sip_reg_uri) {	acc->srv_port = sip_reg_uri->port;    }    /* Create Contact header if not present. */    //if (acc_cfg->contact.slen == 0) {    //	acc_cfg->contact = acc_cfg->id;    //}    /* Build account route-set from outbound proxies and route set from      * account configuration.     */    pj_list_init(&acc->route_set);    for (i=0; i<pjsua_var.ua_cfg.outbound_proxy_cnt; ++i) {    	pj_str_t hname = { "Route", 5};	pjsip_route_hdr *r;	pj_str_t tmp;	pj_strdup_with_null(pjsua_var.pool, &tmp, 			    &pjsua_var.ua_cfg.outbound_proxy[i]);	r = pjsip_parse_hdr(pjsua_var.pool, &hname, tmp.ptr, tmp.slen, NULL);	if (r == NULL) {	    pjsua_perror(THIS_FILE, "Invalid outbound proxy URI",			 PJSIP_EINVALIDURI);	    return PJSIP_EINVALIDURI;	}	pj_list_push_back(&acc->route_set, r);    }    for (i=0; i<acc_cfg->proxy_cnt; ++i) {    	pj_str_t hname = { "Route", 5};	pjsip_route_hdr *r;	pj_str_t tmp;	pj_strdup_with_null(pjsua_var.pool, &tmp, &acc_cfg->proxy[i]);	r = pjsip_parse_hdr(pjsua_var.pool, &hname, tmp.ptr, tmp.slen, NULL);	if (r == NULL) {	    pjsua_perror(THIS_FILE, "Invalid URI in account route set",			 PJ_EINVAL);	    return PJ_EINVAL;	}	pj_list_push_back(&acc->route_set, r);    }        /* Concatenate credentials from account config and global config */    acc->cred_cnt = 0;    for (i=0; i<acc_cfg->cred_count; ++i) {	acc->cred[acc->cred_cnt++] = acc_cfg->cred_info[i];    }    for (i=0; i<pjsua_var.ua_cfg.cred_count && 	      acc->cred_cnt < PJ_ARRAY_SIZE(acc->cred); ++i)    {	acc->cred[acc->cred_cnt++] = pjsua_var.ua_cfg.cred_info[i];    }    status = pjsua_pres_init_acc(acc_id);    if (status != PJ_SUCCESS)	return status;    /* Mark account as valid */    pjsua_var.acc[acc_id].valid = PJ_TRUE;    /* Insert account ID into account ID array, sorted by priority */    for (i=0; i<pjsua_var.acc_cnt; ++i) {	if ( pjsua_var.acc[pjsua_var.acc_ids[i]].cfg.priority <	     pjsua_var.acc[acc_id].cfg.priority)	{	    break;	}    }    pj_array_insert(pjsua_var.acc_ids, sizeof(pjsua_var.acc_ids[0]),		    pjsua_var.acc_cnt, i, &acc_id);    return PJ_SUCCESS;}/* * Add a new account to pjsua. */PJ_DEF(pj_status_t) pjsua_acc_add( const pjsua_acc_config *cfg,				   pj_bool_t is_default,				   pjsua_acc_id *p_acc_id){    unsigned id;    pj_status_t status;    PJ_ASSERT_RETURN(pjsua_var.acc_cnt < PJ_ARRAY_SIZE(pjsua_var.acc),		     PJ_ETOOMANY);    /* Must have a transport */    PJ_ASSERT_RETURN(pjsua_var.tpdata[0].data.ptr != NULL, PJ_EINVALIDOP);    PJSUA_LOCK();    /* Find empty account id. */    for (id=0; id < PJ_ARRAY_SIZE(pjsua_var.acc); ++id) {	if (pjsua_var.acc[id].valid == PJ_FALSE)	    break;    }    /* Expect to find a slot */    PJ_ASSERT_ON_FAIL(	id < PJ_ARRAY_SIZE(pjsua_var.acc), 			{PJSUA_UNLOCK(); return PJ_EBUG;});    /* Copy config */    copy_acc_config(pjsua_var.pool, &pjsua_var.acc[id].cfg, cfg);        /* Normalize registration timeout */    if (pjsua_var.acc[id].cfg.reg_uri.slen &&	pjsua_var.acc[id].cfg.reg_timeout == 0)    {	pjsua_var.acc[id].cfg.reg_timeout = PJSUA_REG_INTERVAL;    }    status = initialize_acc(id);    if (status != PJ_SUCCESS) {	pjsua_perror(THIS_FILE, "Error adding account", status);	PJSUA_UNLOCK();	return status;    }    if (is_default)	pjsua_var.default_acc = id;    if (p_acc_id)	*p_acc_id = id;    pjsua_var.acc_cnt++;    PJSUA_UNLOCK();    PJ_LOG(4,(THIS_FILE, "Account %.*s added with id %d",	      (int)cfg->id.slen, cfg->id.ptr, id));    /* If accounts has registration enabled, start registration */    if (pjsua_var.acc[id].cfg.reg_uri.slen)	pjsua_acc_set_registration(id, PJ_TRUE);    return PJ_SUCCESS;}/* * Add local account */PJ_DEF(pj_status_t) pjsua_acc_add_local( pjsua_transport_id tid,					 pj_bool_t is_default,					 pjsua_acc_id *p_acc_id){    pjsua_acc_config cfg;    pjsua_transport_data *t = &pjsua_var.tpdata[tid];    char uri[PJSIP_MAX_URL_SIZE];    /* ID must be valid */    PJ_ASSERT_RETURN(tid>=0 && tid<PJ_ARRAY_SIZE(pjsua_var.tpdata), PJ_EINVAL);    /* Transport must be valid */    PJ_ASSERT_RETURN(t->data.ptr != NULL, PJ_EINVAL);        pjsua_acc_config_default(&cfg);    /* Lower the priority of local account */    --cfg.priority;    /* Build URI for the account */    pj_ansi_snprintf(uri, PJSIP_MAX_URL_SIZE,		     "<sip:%.*s:%d;transport=%s>", 		     (int)t->local_name.host.slen,		     t->local_name.host.ptr,		     t->local_name.port,		     pjsip_transport_get_type_name(t->type));    cfg.id = pj_str(uri);        return pjsua_acc_add(&cfg, is_default, p_acc_id);}/* * Delete account. */PJ_DEF(pj_status_t) pjsua_acc_del(pjsua_acc_id acc_id){    unsigned i;    PJ_ASSERT_RETURN(acc_id>=0 && acc_id<(int)PJ_ARRAY_SIZE(pjsua_var.acc),		     PJ_EINVAL);    PJ_ASSERT_RETURN(pjsua_var.acc[acc_id].valid, PJ_EINVALIDOP);    PJSUA_LOCK();    /* Delete registration */    if (pjsua_var.acc[acc_id].regc != NULL) {	pjsua_acc_set_registration(acc_id, PJ_FALSE);	pjsip_regc_destroy(pjsua_var.acc[acc_id].regc);	pjsua_var.acc[acc_id].regc = NULL;    }    /* Delete server presence subscription */    pjsua_pres_delete_acc(acc_id);    /* Invalidate */    pjsua_var.acc[acc_id].valid = PJ_FALSE;    /* Remove from array */    for (i=0; i<pjsua_var.acc_cnt; ++i) {	if (pjsua_var.acc_ids[i] == acc_id)	    break;    }    if (i != pjsua_var.acc_cnt) {	pj_array_erase(pjsua_var.acc_ids, sizeof(pjsua_var.acc_ids[0]),		       pjsua_var.acc_cnt, i);	--pjsua_var.acc_cnt;    }    /* Leave the calls intact, as I don't think calls need to     * access account once it's created     */    PJSUA_UNLOCK();    PJ_LOG(4,(THIS_FILE, "Account id %d deleted", acc_id));    return PJ_SUCCESS;}/* * Modify account information. */PJ_DEF(pj_status_t) pjsua_acc_modify( pjsua_acc_id acc_id,				      const pjsua_acc_config *cfg){    PJ_TODO(pjsua_acc_modify);    PJ_UNUSED_ARG(acc_id);    PJ_UNUSED_ARG(cfg);    return PJ_EINVALIDOP;}/* * Modify account's presence status to be advertised to remote/presence * subscribers. */PJ_DEF(pj_status_t) pjsua_acc_set_online_status( pjsua_acc_id acc_id,						 pj_bool_t is_online){    PJ_ASSERT_RETURN(acc_id>=0 && acc_id<(int)PJ_ARRAY_SIZE(pjsua_var.acc),		     PJ_EINVAL);    PJ_ASSERT_RETURN(pjsua_var.acc[acc_id].valid, PJ_EINVALIDOP);    pjsua_var.acc[acc_id].online_status = is_online;    pjsua_pres_refresh();    return PJ_SUCCESS;}/* * This callback is called by pjsip_regc when outgoing register * request has completed. */static void regc_cb(struct pjsip_regc_cbparam *param){    pjsua_acc *acc = param->token;    PJSUA_LOCK();    /*     * Print registration status.     */    if (param->status!=PJ_SUCCESS) {	pjsua_perror(THIS_FILE, "SIP registration error", 		     param->status);	pjsip_regc_destroy(acc->regc);	acc->regc = NULL;	    } else if (param->code < 0 || param->code >= 300) {	PJ_LOG(2, (THIS_FILE, "SIP registration failed, status=%d (%.*s)", 		   param->code, 		   (int)param->reason.slen, param->reason.ptr));	pjsip_regc_destroy(acc->regc);	acc->regc = NULL;    } else if (PJSIP_IS_STATUS_IN_CLASS(param->code, 200)) {	if (param->expiration < 1) {	    pjsip_regc_destroy(acc->regc);	    acc->regc = NULL;	    PJ_LOG(3,(THIS_FILE, "%s: unregistration success",		      pjsua_var.acc[acc->index].cfg.id.ptr));	} else {	    PJ_LOG(3, (THIS_FILE, 		       "%s: registration success, status=%d (%.*s), "		       "will re-register in %d seconds", 		       pjsua_var.acc[acc->index].cfg.id.ptr,		       param->code,		       (int)param->reason.slen, param->reason.ptr,		       param->expiration));	    /* Send initial PUBLISH if it is enabled */	    if (acc->cfg.publish_enabled && acc->publish_sess==NULL)		pjsua_pres_init_publish_acc(acc->index);	}    } else {	PJ_LOG(4, (THIS_FILE, "SIP registration updated status=%d", param->code));    }    acc->reg_last_err = param->status;    acc->reg_last_code = param->code;    if (pjsua_var.ua_cfg.cb.on_reg_state)	(*pjsua_var.ua_cfg.cb.on_reg_state)(acc->index);    PJSUA_UNLOCK();}/* * Initialize client registration. */static pj_status_t pjsua_regc_init(int acc_id){    pjsua_acc *acc;    pj_str_t contact;    char contact_buf[1024];    pj_pool_t *pool;    pj_status_t status;    PJ_ASSERT_RETURN(pjsua_acc_is_valid(acc_id), PJ_EINVAL);    acc = &pjsua_var.acc[acc_id];    if (acc->cfg.reg_uri.slen == 0) {	PJ_LOG(3,(THIS_FILE, "Registrar URI is not specified"));	return PJ_SUCCESS;    }    /* Destroy existing session, if any */    if (acc->regc) {	pjsip_regc_destroy(acc->regc);	acc->regc = NULL;    }    /* initialize SIP registration if registrar is configured */    status = pjsip_regc_create( pjsua_var.endpt, 				acc, &regc_cb, &acc->regc);    if (status != PJ_SUCCESS) {	pjsua_perror(THIS_FILE, "Unable to create client registration", 		     status);	return status;    }    pool = pj_pool_create_on_buf(NULL, contact_buf, sizeof(contact_buf));    status = pjsua_acc_create_uac_contact( pool, &contact,					   acc_id, &acc->cfg.reg_uri);    if (status != PJ_SUCCESS) {	pjsua_perror(THIS_FILE, "Unable to generate suitable Contact header"				" for registration", 		     status);	return status;    }    status = pjsip_regc_init( acc->regc,			      &acc->cfg.reg_uri, 			      &acc->cfg.id, 			      &acc->cfg.id,			      1, &contact, 			      acc->cfg.reg_timeout);    if (status != PJ_SUCCESS) {	pjsua_perror(THIS_FILE, 		     "Client registration initialization error", 		     status);	return status;    }    /* If account is locked to specific transport, then set transport to     * the client registration.     */    if (pjsua_var.acc[acc_id].cfg.transport_id != PJSUA_INVALID_ID) {	pjsip_tpselector tp_sel;	pjsua_init_tpselector(pjsua_var.acc[acc_id].cfg.transport_id, &tp_sel);	pjsip_regc_set_transport(acc->regc, &tp_sel);    }    /* Set credentials     */    if (acc->cred_cnt) {	pjsip_regc_set_credentials( acc->regc, acc->cred_cnt, acc->cred);    }    /* Set route-set     */    if (!pj_list_empty(&acc->route_set)) {	pjsip_regc_set_route_set( acc->regc, &acc->route_set );    }    /* Add other request headers. */    if (pjsua_var.ua_cfg.user_agent.slen) {	pjsip_hdr hdr_list;	const pj_str_t STR_USER_AGENT = { "User-Agent", 10 };	pjsip_generic_string_hdr *h;	pool = pj_pool_create_on_buf(NULL, contact_buf, sizeof(contact_buf));	pj_list_init(&hdr_list);	h = pjsip_generic_string_hdr_create(pool, &STR_USER_AGENT, 					    &pjsua_var.ua_cfg.user_agent);	pj_list_push_back(&hdr_list, (pjsip_hdr*)h);	pjsip_regc_add_headers(acc->regc, &hdr_list);    }    return PJ_SUCCESS;}

⌨️ 快捷键说明

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