📄 pjsua_acc.c
字号:
/* $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));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -