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

📄 pdt.c

📁 性能优秀的SIP Proxy
💻 C
📖 第 1 页 / 共 2 页
字号:
/** * $Id: pdt.c,v 1.8 2006/07/03 15:26:17 miconda Exp $ * * Copyright (C) 2001-2003 FhG Fokus * * This file is part of openser, a free SIP server. * * openser 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 * * openser 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 * * History: * ------- * 2003-04-07: a structure for both hashes introduced (ramona)  * 2003-04-06: db connection closed in mod_init (janakj) * 2004-06-07: updated to the new DB api (andrei) * 2005-01-26: removed terminating code (ramona) *             prefix hash replaced with tree (ramona) *             FIFO commands to add/list/delete prefix domains (ramona) *             pdt cache per process for fast translation (ramona) * 2006-01-30: multi domain support added *//* * Prefix-Domains Translation - ser module * Ramona Modroiu <ramona@voice-system.ro> */#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include "../../db/db_op.h"#include "../../sr_module.h"#include "../../db/db.h"#include "../../mem/shm_mem.h"#include "../../mem/mem.h"#include "../../dprint.h"#include "../../fifo_server.h"#include "../../unixsock_server.h"#include "../../parser/parse_uri.h"#include "../../timer.h"#include "../../ut.h"#include "../../action.h"#include "../../parser/parse_from.h"#include "domains.h"#include "pdtree.h"MODULE_VERSION#define NR_KEYS			3int hs_two_pow = 2;/** structures containing prefix-domain pairs */hash_list_t *_dhash = NULL; pdt_tree_t *_ptree = NULL; time_t last_sync;/** database connection */static db_con_t *db_con = NULL;static db_func_t pdt_dbf;/** parameters */static char *db_url = "mysql://root@127.0.0.1/pdt";char *db_table = "pd_multidomain";char *sdomain_column = "sdomain";char *prefix_column  = "prefix";char *domain_column  = "domain";/** pstn prefix */str prefix = {"", 0};int sync_time = 600;int clean_time = 900;static int w_prefix2domain(struct sip_msg* msg, char* str1, char* str2);static int w_prefix2domain_1(struct sip_msg* msg, char* mode, char* str2);static int mod_init(void);static void mod_destroy(void);static int  child_init(int r);static int prefix2domain(struct sip_msg*, int mode);static int get_domainprefix_unixsock(str* msg);static int pdt_fifo_add(FILE *stream, char *response_file);static int pdt_fifo_delete(FILE *stream, char *response_file);static int pdt_fifo_list(FILE *stream, char *response_file);int update_new_uri(struct sip_msg *msg, int plen, str *d, int mode);int pdt_load_db();int pdt_sync_cache();void pdt_clean_cache(unsigned int ticks, void *param);static cmd_export_t cmds[]={	{"prefix2domain", w_prefix2domain,   0, 0, REQUEST_ROUTE|FAILURE_ROUTE},	{"prefix2domain", w_prefix2domain_1, 1, 0, REQUEST_ROUTE|FAILURE_ROUTE},	{0, 0, 0, 0, 0}};static param_export_t params[]={	{"db_url",         STR_PARAM, &db_url},	{"db_table",       STR_PARAM, &db_table},	{"sdomain_column", STR_PARAM, &sdomain_column},	{"prefix_column",  STR_PARAM, &prefix_column},	{"domain_column",  STR_PARAM, &domain_column},	{"prefix",         STR_PARAM, &prefix.s},	{"hsize_2pow",     INT_PARAM, &hs_two_pow},	{"sync_time",      INT_PARAM, &sync_time},	{"clean_time",     INT_PARAM, &clean_time},	{0, 0, 0}};struct module_exports exports = {	"pdt",	cmds,	params,	0,		mod_init,		/* module initialization function */	0,				/* response function */	mod_destroy,	/* destroy function */	child_init		/* per child init function */};	/** * init module function */static int mod_init(void){	DBG("PDT: initializing...\n");	if(hs_two_pow<0)	{		LOG(L_ERR, "PDT:mod_init: hash_size_two_pow must be"					" positive and less than %d\n", MAX_HSIZE_TWO_POW);		return -1;	}	prefix.len = strlen(prefix.s);		if(register_fifo_cmd(pdt_fifo_add, "pdt_add", 0)<0)	{		LOG(L_ERR,			"PDT:mod_init: cannot register fifo command 'pdt_add'\n");		return -1;	}		if(register_fifo_cmd(pdt_fifo_delete, "pdt_delete", 0)<0)	{		LOG(L_ERR,			"PDT:mod_init: cannot register fifo command 'pdt_delete'\n");		return -1;	}		if(register_fifo_cmd(pdt_fifo_list, "pdt_list", 0)<0)	{		LOG(L_ERR,			"PDT:mod_init: cannot register fifo command 'pdt_list'\n");		return -1;	}		if(unixsock_register_cmd("get_domainprefix", get_domainprefix_unixsock)<0)	{		LOG(L_ERR,		"PDT:mod_init: cannot register unixsock command 'get_domainprefix'\n");		return -1;	}	/* binding to mysql module */	if(bind_dbmod(db_url, &pdt_dbf))	{		LOG(L_ERR, "PDT:mod_init: Database module not found\n");		return -1;	}	if (!DB_CAPABILITY(pdt_dbf, DB_CAP_ALL))	{		LOG(L_ERR, "PDT: mod_init: Database module does not "		    "implement all functions needed by the module\n");		return -1;	}	/* open a connection with the database */	db_con = pdt_dbf.init(db_url);	if(db_con==NULL)	{		LOG(L_ERR,			"PDT: mod_init: Error while connecting to database\n");        		return -1;	}		if (pdt_dbf.use_table(db_con, db_table) < 0)	{		LOG(L_ERR, "PDT: mod_init: Error in use_table\n");		goto error1;	}	DBG("PDT: mod_init: Database connection opened successfully\n");		/* init the hash and tree in share memory */	if( (_dhash = init_hash_list(hs_two_pow)) == NULL)	{		LOG(L_ERR, "PDT:mod_init: domain hash could not be allocated\n");			goto error1;	}		/* loading all information from database */	if(pdt_load_db()!=0)	{		LOG(L_ERR, "PDT:mod_init: cannot load info from database\n");			goto error2;	}			pdt_dbf.close(db_con);	db_con = 0;	pdt_print_tree(_ptree);	DBG("PDT:mod_init: -------------------\n");	pdt_print_hash_list(_dhash);	last_sync = time(NULL);	register_timer(pdt_clean_cache, 0, clean_time);	/* success code */	return 0;error2:	if(_dhash!=NULL)	{		free_hash_list(_dhash);		_dhash = 0;	}error1:	if(db_con!=NULL)	{		pdt_dbf.close(db_con);		db_con = 0;	}	return -1;}	/* each child get a new connection to the database */static int child_init(int r){	DBG("PDT:child_init #%d / pid <%d>\n", r, getpid());	if(r>0)	{		if(_dhash==NULL)		{			LOG(L_ERR,"PDT:child_init #%d: ERROR no domain hash\n", r);			return -1;		}			lock_get(&_dhash->hl_lock);		_dhash->workers++;		lock_release(&_dhash->hl_lock);	} else {		if(_ptree!=NULL)		{			pdt_free_tree(_ptree);			_ptree = 0;		}	}		db_con = pdt_dbf.init(db_url);	if(db_con==NULL)	{	  LOG(L_ERR,"PDT:child_init #%d: Error while connecting database\n",r);	  return -1;	}		if (pdt_dbf.use_table(db_con, db_table) < 0)	{		LOG(L_ERR, "PDT:child_init #%d: Error in use_table\n", r);		return -1;	}	if(sync_time<=0)		sync_time = 300;	sync_time += r%60;	DBG("PDT:child_init #%d: Database connection opened successfully\n",r);		return 0;}static void mod_destroy(void){	DBG("PDT: mod_destroy : Cleaning up\n");	if (_dhash!=NULL)		free_hash_list(_dhash);	if (_ptree!=NULL)		pdt_free_tree(_ptree);	if (db_con!=NULL && pdt_dbf.close!=NULL)		pdt_dbf.close(db_con);}static int w_prefix2domain(struct sip_msg* msg, char* str1, char* str2){	return prefix2domain(msg, 0);}static int w_prefix2domain_1(struct sip_msg* msg, char* mode, char* str2){	if(mode!=NULL && *mode=='1')		return prefix2domain(msg, 1);	else if(mode!=NULL && *mode=='2')			return prefix2domain(msg, 2);	else return prefix2domain(msg, 0);}/* change the r-uri if it is a PSTN format */static int prefix2domain(struct sip_msg* msg, int mode){	str *d, p;	time_t crt_time;	int plen;	struct sip_uri uri;		if(msg==NULL)	{		LOG(L_ERR,"PDT:prefix2domain: weird error\n");		return -1;	}		/* parse the uri, if not yet */	if(msg->parsed_uri_ok==0)		if(parse_sip_msg_uri(msg)<0)		{			LOG(L_ERR,"PDT:prefix2domain: ERROR while parsing the R-URI\n");			return -1;		}	/* if the user part begin with the prefix for PSTN users, extract the code*/	if (msg->parsed_uri.user.len<=0)	{		DBG("PDT:prefix2domain: user part of the message is empty\n");		return 1;	}		if(prefix.len>0 && prefix.len < msg->parsed_uri.user.len			&& strncasecmp(prefix.s, msg->parsed_uri.user.s, prefix.len)!=0)	{		DBG("PDT:prefix2domain: PSTN prefix did not matched\n");		return 1;				}	p.s   = msg->parsed_uri.user.s + prefix.len;	p.len = msg->parsed_uri.user.len - prefix.len;	pdt_print_tree(_ptree);	/* check if need for sync */	crt_time = time(NULL);	if(last_sync + sync_time < crt_time)	{		last_sync = crt_time;		if(pdt_sync_cache())		{			LOG(L_ERR, "PDT:prefix2domain: cannot update the cache\n");			return -1;		}	}	/* take the domain from  FROM uri as sdomain */	if(parse_from_header(msg)<0 ||  msg->from == NULL || get_from(msg)==NULL)	{		LOG(L_ERR,			"prefix_to_domain: ERROR cannot parse FROM header\n");		return -1;	}				memset(&uri, 0, sizeof(struct sip_uri));	if (parse_uri(get_from(msg)->uri.s, get_from(msg)->uri.len , &uri)<0)	{		LOG(L_ERR,"prefix_to_domain: failed to parse From uri\n");		return -1;	}//	pdt_print_tree(_ptree);		/* find the domain that corresponds to this prefix */	plen = 0;	if((d=pdt_get_domain(_ptree, &uri.host, &p, &plen))==NULL)	{		LOG(L_INFO, "PDT:prefix2domain: no prefix found in [%.*s]\n",				p.len, p.s);		return -1;	}		/* update the new uri */	if(update_new_uri(msg, plen, d, mode)<0)	{		LOG(L_ERR, "PDT:prefix2domain: new_uri cannot be updated\n");		return -1;	}	return 1;}/* change the uri according to translation of the prefix */int update_new_uri(struct sip_msg *msg, int plen, str *d, int mode){	struct action act;	if(msg==NULL || d==NULL)	{		LOG(L_ERR, "PDT:update_new_uri: bad parameters\n");		return -1;	}		if(mode==0 || (mode==1 && prefix.len>0))	{		act.type = STRIP_T;		act.p1_type = NUMBER_ST;		if(mode==0)			act.p1.number = plen + prefix.len;		else			act.p1.number = prefix.len;		act.next = 0;		if (do_action(&act, msg) < 0)		{			LOG(L_ERR, "PDT:update_new_uri:Error removing prefix\n");			return -1;		}	}		act.type = SET_HOSTPORT_T;	act.p1_type = STRING_ST;	act.p1.string = d->s;	act.next = 0;	if (do_action(&act, msg) < 0)	{		LOG(L_ERR, "PDT:update_new_uri:Error changing domain\n");		return -1;	}	DBG("PDT: update_new_uri: len=%d uri=%.*s\n", msg->new_uri.len, 			msg->new_uri.len, msg->new_uri.s);		return 0;}int pdt_load_db(){	db_key_t db_cols[3] = {sdomain_column, prefix_column, domain_column};	str p, d, sdomain;	db_res_t* db_res = NULL;	int i;			if(db_con==NULL)	{		LOG(L_ERR, "PDT:pdt_load_db: no db connection\n");		return -1;	}			if (pdt_dbf.use_table(db_con, db_table) < 0)	{		LOG(L_ERR, "PDT:pdt_load_db: Error in use_table\n");		return -1;	}		if(pdt_dbf.query(db_con, NULL, NULL, NULL, db_cols,				0, 3, sdomain_column, &db_res)==0)	{		for(i=0; i<RES_ROW_N(db_res); i++)		{			/* check for NULL values ?!?! */			sdomain.s = (char*)(RES_ROWS(db_res)[i].values[0].val.string_val);			sdomain.len = strlen(sdomain.s);			p.s = (char*)(RES_ROWS(db_res)[i].values[1].val.string_val);			p.len = strlen(p.s);						d.s = (char*)(RES_ROWS(db_res)[i].values[2].val.string_val);			d.len = strlen(d.s);			if(p.s==NULL || d.s==NULL || sdomain.s==NULL ||					p.len<=0 || d.len<=0 || sdomain.len<=0)			{				LOG(L_ERR, "PDT:pdt_load_db: Error - bad values in db\n");				goto error;			}					if(pdt_check_pd(_dhash, &sdomain, &p, &d)==1)			{				LOG(L_ERR,				"PDT:pdt_load_db:sdomain [%.*s]: prefix [%.*s] or domain <%.*s> duplicated\n",					sdomain.len, sdomain.s, p.len, p.s, d.len, d.s);				goto error;			}			if(pdt_add_to_tree(&_ptree, &sdomain, &p, &d)<0)			{				LOG(L_ERR, "PDT:pdt_load_db: Error adding info to tree\n");				goto error;			}						if(pdt_add_to_hash(_dhash, &sdomain, &p, &d)!=0)			{				LOG(L_ERR, "PDT:pdt_load_db: Error adding info to hash\n");				goto error;			} 		}	}		pdt_dbf.free_result(db_con, db_res);	return 0;error:	pdt_dbf.free_result(db_con, db_res);	return -1;}int pdt_sync_cache(){	pd_op_t *ito;	hash_t *it;	pdt_tree_t *itree;		DBG("PDT:pdt_sync_cache: ...\n");	if(_dhash==NULL || _ptree==NULL)	{		LOG(L_ERR, "PDT:pdt_sync_cache: strange situation\n");		return -1;	}		lock_get(&_dhash->hl_lock);	it = _dhash->hash;	while(it != NULL)	{		itree = pdt_get_tree(_ptree, &it->sdomain);		if(itree!=NULL && itree->idsync >= it->max_id)			continue; 		ito = it->diff;		while(ito!=NULL && itree->idsync >= ito->id)			ito = ito->n;				while(ito!=NULL && itree->idsync<ito->id)		{			DBG("PDT:pdt_sync_cache: sync op[%d]=%d...\n",				ito->id, ito->op);			switch(ito->op)			{				case PDT_ADD:					if(pdt_add_to_tree(&_ptree, &it->sdomain, &ito->cell->prefix,								&ito->cell->domain)<0)					{						LOG(L_ERR, "PDT:pdt_sync_cache: Error to insert into tree\n");						goto error;

⌨️ 快捷键说明

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