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

📄 dispatch.c

📁 性能优秀的SIP Proxy
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * $Id: dispatch.c,v 1.11 2006/05/07 20:48:52 miconda Exp $ * * dispatcher module * * Copyright (C) 2004-2006 FhG Fokus * Copyright (C) 2005 Voice-System.ro * * 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 * ------- * 2004-07-31  first version, by daniel * 2005-04-22  added ruri  & to_uri hashing (andrei) * 2005-12-10  added failover support via avp (daniel) *  */#include <stdio.h>#include <string.h>#include <stdlib.h>#include "../../trim.h"#include "../../dprint.h"#include "../../action.h"#include "../../route.h"#include "../../dset.h"#include "../../mem/shm_mem.h"#include "../../parser/parse_uri.h"#include "../../parser/parse_from.h"#include "../../usr_avp.h"#include "dispatch.h"typedef struct _ds_setidx{	int id;	int index;	struct _ds_setidx *next;} ds_setidx_t, *ds_setidx_p;typedef struct _ds_dest{	str uri;	int flags;	struct _ds_dest *next;} ds_dest_t, *ds_dest_p;typedef struct _ds_set{	int id;				/* id of dst set */	int nr;				/* number of items in dst set */	int index;			/* index pf dst set */	int last;			/* last used item in dst set */	ds_dest_p dlist;	struct _ds_set *next;} ds_set_t, *ds_set_p;extern int ds_force_dst;ds_setidx_p _ds_index = NULL;ds_set_p _ds_list = NULL;int _ds_list_nr = 0;/** * */int ds_load_list(char *lfile){	char line[256], *p;	FILE *f = NULL;	int id, i, j, setn;	str uri;	struct sip_uri puri;	ds_dest_p dp = NULL, dp0 = NULL;	ds_set_p  sp = NULL, sp0 = NULL;	ds_setidx_p si = NULL, si0 = NULL;		if(lfile==NULL || strlen(lfile)<=0)	{		LOG(L_ERR, "DISPATCHER:ds_load_list: bad list file\n");		return -1;	}	f = fopen(lfile, "r");	if(f==NULL)	{		LOG(L_ERR, "DISPATCHER:ds_load_list: can't open list file [%s]\n",				lfile);		return -1;			}	id = setn = 0;	p = fgets(line, 256, f);	while(p)	{		/* eat all white spaces */		while(*p && (*p==' ' || *p=='\t' || *p=='\r' || *p=='\n'))			p++;		if(*p=='\0' || *p=='#')			goto next_line;				/* get set id */		id = 0;		while(*p>='0' && *p<='9')		{			id = id*10+ (*p-'0');			p++;		}				/* eat all white spaces */		while(*p && (*p==' ' || *p=='\t' || *p=='\r' || *p=='\n'))			p++;		if(*p=='\0' || *p=='#')		{			LOG(L_ERR, "DISPATCHER:ds_load_list: bad line [%s]\n", line);			goto error;		}		/* get uri */		uri.s = p;		while(*p && *p!=' ' && *p!='\t' && *p!='\r' && *p!='\n' && *p!='#')			p++;		uri.len = p-uri.s;		/* check uri */		if(parse_uri(uri.s, uri.len, &puri)!=0)		{			LOG(L_ERR, "DISPATCHER:ds_load_list: bad uri [%.*s]\n",					uri.len, uri.s);			goto error;		}				/* check index */		si = _ds_index;		while(si)		{			if(si->id == id)				break;			si = si->next;		}		if(si==NULL)		{			si = (ds_setidx_p)shm_malloc(sizeof(ds_setidx_t));			if(si==NULL)			{				LOG(L_ERR, "DISPATCHER:ds_load_list: no more memory\n");				goto error;			}			memset(si, 0, sizeof(ds_setidx_t));			si->id = id;			si->next = _ds_index;			if(_ds_index!=NULL)				si->index = _ds_index->index + 1;						_ds_index = si;		}				/* get dest set */		sp = _ds_list;		while(sp)		{			if(sp->id == id)				break;			sp = sp->next;		}		if(sp==NULL)		{			sp = (ds_set_p)shm_malloc(sizeof(ds_set_t));			if(sp==NULL)			{				LOG(L_ERR, "DISPATCHER:ds_load_list: no more memory.\n");				goto error;			}			memset(sp, 0, sizeof(ds_set_t));			sp->next = _ds_list;			_ds_list = sp;			setn++;		}		sp->id = id;		sp->nr++;		sp->index = si->index;		/* store uri */		dp = (ds_dest_p)shm_malloc(sizeof(ds_dest_t));		if(dp==NULL)		{			LOG(L_ERR, "DISPATCHER:ds_load_list: no more memory!\n");			goto error;		}		memset(dp, 0, sizeof(ds_dest_t));		dp->uri.s = (char*)shm_malloc(uri.len+1);		if(dp->uri.s==NULL)		{			LOG(L_ERR, "DISPATCHER:ds_load_list: no more memory!!\n");			shm_free(dp);			goto error;		}		strncpy(dp->uri.s, uri.s, uri.len);		dp->uri.s[uri.len]='\0';		dp->uri.len = uri.len;		dp->next = sp->dlist;		sp->dlist = dp;		DBG("DISPATCHER:ds_load_list: dest [%d/%d/%d] <%.*s>\n", sp->index,				sp->id, sp->nr, dp->uri.len, dp->uri.s);		next_line:		p = fgets(line, 256, f);	}			fclose(f);	f = NULL;		DBG("DISPATCHER:ds_load_list: found [%d] dest sets\n", setn);		/* re-index destination sets for fast access */	sp0 = (ds_set_p)shm_malloc(setn*sizeof(ds_set_t));	if(sp0==NULL)	{		LOG(L_ERR, "DISPATCHER:ds_load_list: no more memory!!\n");		goto error;	}	memset(sp0, 0, setn*sizeof(ds_set_t));	sp = _ds_list;	for(i=setn-1; i>=0; i--)	{		memcpy(&sp0[i], sp, sizeof(ds_set_t));		if(i==setn-1)			sp0[i].next = NULL;		else			sp0[i].next = &sp0[i+1];		dp0 = (ds_dest_p)shm_malloc(sp0[i].nr*sizeof(ds_dest_t));		if(dp0==NULL)		{			LOG(L_ERR, "DISPATCHER:ds_load_list: no more memory!\n");			ds_destroy_list();			goto error;		}		memset(dp0, 0, sp0[i].nr*sizeof(ds_dest_t));		dp = sp0[i].dlist;		for(j=sp0[i].nr-1; j>=0; j--)		{			memcpy(&dp0[j], dp, sizeof(ds_dest_t));			if(j==sp0[j].nr-1)				dp0[j].next = NULL;			else				dp0[j].next = &dp0[j+1];			dp = dp->next;		}		sp0[i].dlist = dp0;		sp = sp->next;	}		sp = _ds_list;	_ds_list = sp0;	while(sp)	{		dp = sp->dlist;		while(dp)		{			dp0 = dp;			dp = dp->next;			shm_free(dp0);		}		sp0 = sp;		sp = sp->next;		shm_free(sp0);	}	_ds_list_nr = setn;		return 0;error:	if(f!=NULL)		fclose(f);	si = _ds_index;	while(si)	{		si0 = si;		si = si->next;		shm_free(si0);	}	_ds_index = NULL;	sp = _ds_list;	while(sp)	{		dp = sp->dlist;		while(dp)		{			if(dp->uri.s!=NULL)				shm_free(dp->uri.s);			dp->uri.s=NULL;			dp0 = dp;			dp = dp->next;			shm_free(dp0);		}		sp0 = sp;		sp = sp->next;		shm_free(sp0);	}	return -1;}/** * */int ds_destroy_list(){	int i;	ds_set_p  sp = NULL;	ds_setidx_p si = NULL, si0 = NULL;		sp = _ds_list;	while(sp)	{		for(i=0; i<sp->nr; i++)		{			if(sp->dlist[i].uri.s!=NULL)			{				shm_free(sp->dlist[i].uri.s);				sp->dlist[i].uri.s = NULL;			}		}		shm_free(sp->dlist);		sp = sp->next;	}	if (_ds_list) shm_free(_ds_list);		si = _ds_index;	while(si)	{		si0 = si;		si = si->next;		shm_free(si0);	}	_ds_index = NULL;	return 0;}/** * */unsigned int ds_get_hash(str *x, str *y){	char* p;	register unsigned v;	register unsigned h;	if(!x && !y)		return 0;	h=0;	if(x)	{		p=x->s;		if (x->len>=4)		{			for (; p<=(x->s+x->len-4); p+=4)			{				v=(*p<<24)+(p[1]<<16)+(p[2]<<8)+p[3];				h+=v^(v>>3);			}		}		v=0;		for (;p<(x->s+x->len); p++)		{ 			v<<=8; 			v+=*p;		}		h+=v^(v>>3);	}	if(y)	{		p=y->s;		if (y->len>=4) 		{			for (; p<=(y->s+y->len-4); p+=4)			{				v=(*p<<24)+(p[1]<<16)+(p[2]<<8)+p[3];				h+=v^(v>>3);			}		}			v=0;		for (;p<(y->s+y->len); p++)		{ 			v<<=8; 			v+=*p;		}		h+=v^(v>>3);	}	h=((h)+(h>>11))+((h>>13)+(h>>23));	return (h)?h:1;}/* * gets the part of the uri we will use as a key for hashing * params:  key1       - will be filled with first part of the key *                       (uri user or "" if no user) *          key2       - will be filled with the second part of the key *                       (uri host:port) *          uri        - str with the whole uri *          parsed_uri - struct sip_uri pointer with the parsed uri *                       (it must point inside uri). It can be null *                       (in this case the uri will be parsed internally). *          flags  -    if & DS_HASH_USER_ONLY, only the user part of the uri *                      will be used * returns: -1 on error, 0 on success */static inline int get_uri_hash_keys(str* key1, str* key2,							str* uri, struct sip_uri* parsed_uri, int flags){	struct sip_uri tmp_p_uri; /* used only if parsed_uri==0 */		if (parsed_uri==0){		if (parse_uri(uri->s, uri->len, &tmp_p_uri)<0){			LOG(L_ERR, "DISPATCHER: get_uri_hash_keys: invalid uri %.*s\n",					uri->len, uri->len?uri->s:"");			goto error;		}		parsed_uri=&tmp_p_uri;	}	/* uri sanity checks */	if (parsed_uri->host.s==0){			LOG(L_ERR, "DISPATCHER: get_uri_hash_keys: invalid uri, no host"					   "present: %.*s\n", uri->len, uri->len?uri->s:"");			goto error;	}		/* we want: user@host:port if port !=5060	 *          user@host if port==5060	 *          user if the user flag is set*/	*key1=parsed_uri->user;	key2->s=0;	key2->len=0;	if (!(flags & DS_HASH_USER_ONLY)){		/* key2=host */		*key2=parsed_uri->host;		/* add port if needed */		if (parsed_uri->port.s!=0){ /* uri has a port */			/* skip port if == 5060 or sips and == 5061 */			if (parsed_uri->port_no !=					((parsed_uri->type==SIPS_URI_T)?SIPS_PORT:SIP_PORT))				key2->len+=parsed_uri->port.len+1 /* ':' */;		}	}	if (key1->s==0){		LOG(L_WARN, "DISPATCHER: get_uri_hashs_keys: empty username in:"					" %.*s\n", uri->len, uri->len?uri->s:"");	}	return 0;error:	return -1;}/** * */int ds_hash_fromuri(struct sip_msg *msg, unsigned int *hash){	str from;	str key1;	str key2;		if(msg==NULL || hash == NULL)	{		LOG(L_ERR, "DISPATCHER:ds_hash_fromuri: bad parameters\n");		return -1;	}		if(parse_from_header(msg)<0)	{		LOG(L_ERR, "DISPATCHER:ds_hash_fromuri:ERROR cannot parse From hdr\n");		return -1;	}		if(msg->from==NULL || get_from(msg)==NULL)	{		LOG(L_ERR, "DISPATCHER:ds_hash_fromuri:ERROR cannot get From uri\n");		return -1;

⌨️ 快捷键说明

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