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

📄 h_table.c

📁 用来作为linux中SIP SERVER,完成VOIP网络电话中服务器的功能
💻 C
字号:
/* * $Id: h_table.c,v 1.91.2.1 2005/07/27 12:32:22 andrei Exp $ * * Copyright (C) 2001-2003 FhG Fokus * * This file is part of ser, a free SIP server. * * ser 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 * * For a license to use the ser software under conditions * other than those described here, or to purchase support for this * software, please contact iptel.org by e-mail at the following addresses: *    info@iptel.org * * ser 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-03-06  200/INV to-tag list deallocation added; *             setting "kill_reason" moved in here -- it is moved *             from transaction state to a static var(jiri) * 2003-03-16  removed _TOTAG (jiri) * 2003-03-30  set_kr for requests only (jiri) * 2003-04-04  bug_fix: REQ_IN callback not called for local  *             UAC transactions (jiri) * 2003-09-12  timer_link->tg will be set only if EXTRA_DEBUG (andrei) * 2003-12-04  global callbacks replaceed with callbacks per transaction; *             completion callback merged into them as LOCAL_COMPETED (bogdan) * 2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri) * 2004-02-13  t->is_invite and t->local replaced with flags; *             timer_link.payload removed (bogdan) * 2004-08-23  avp support added - move and remove avp list to/from *             transactions (bogdan) */#include <stdlib.h>#include "../../mem/shm_mem.h"#include "../../hash_func.h"#include "../../dprint.h"#include "../../md5utils.h"#include "../../ut.h"#include "../../globals.h"#include "../../error.h"#include "../../fifo_server.h"#include "../../unixsock_server.h"#include "defs.h"#include "t_reply.h"#include "t_cancel.h"#include "t_stats.h"#include "h_table.h"#include "fix_lumps.h" /* free_via_clen_lump */static enum kill_reason kr;/* pointer to the big table where all the transaction data   lives */static struct s_table*  tm_table;void set_kr( enum kill_reason _kr ){	kr|=_kr;}enum kill_reason get_kr() {	return kr;}void lock_hash(int i) {	lock(&tm_table->entrys[i].mutex);}void unlock_hash(int i) {	unlock(&tm_table->entrys[i].mutex);}struct s_table* get_tm_table(){	return tm_table;}unsigned int transaction_count( void ){	unsigned int i;	unsigned int count;	count=0;		for (i=0; i<TABLE_ENTRIES; i++) 		count+=tm_table->entrys[i].cur_entries;	return count;}void free_cell( struct cell* dead_cell ){	char *b;	int i;	struct sip_msg *rpl;	struct totag_elem *tt, *foo;	struct tm_callback *cbs, *cbs_tmp;	release_cell_lock( dead_cell );	shm_lock();	/* UA Server */	if ( dead_cell->uas.request )		sip_msg_free_unsafe( dead_cell->uas.request );	if ( dead_cell->uas.response.buffer )		shm_free_unsafe( dead_cell->uas.response.buffer );	/* callbacks */	for( cbs=dead_cell->tmcb_hl.first ; cbs ; ) {		cbs_tmp = cbs;		cbs = cbs->next;		shm_free_unsafe( cbs_tmp );	}	/* UA Clients */	for ( i =0 ; i<dead_cell->nr_of_outgoings;  i++ )	{		/* retransmission buffer */		if ( (b=dead_cell->uac[i].request.buffer) )			shm_free_unsafe( b );		b=dead_cell->uac[i].local_cancel.buffer;		if (b!=0 && b!=BUSY_BUFFER)			shm_free_unsafe( b );		rpl=dead_cell->uac[i].reply;		if (rpl && rpl!=FAKED_REPLY) {			sip_msg_free_unsafe( rpl );		}	}	/* collected to tags */	tt=dead_cell->fwded_totags;	while(tt) {		foo=tt->next;		shm_free_unsafe(tt->tag.s);		shm_free_unsafe(tt);		tt=foo;	}	/* free the avp list */	if (dead_cell->user_avps)		destroy_avp_list_unsafe( &dead_cell->user_avps );	/* the cell's body */	shm_free_unsafe( dead_cell );	shm_unlock();}static inline void init_synonym_id( struct cell *t ){	struct sip_msg *p_msg;	int size;	char *c;	unsigned int myrand;	if (!syn_branch) {		p_msg=t->uas.request;		if (p_msg) {			/* char value of a proxied transaction is			   calculated out of header-fields forming			   transaction key			*/			char_msg_val( p_msg, t->md5 );		} else {			/* char value for a UAC transaction is created			   randomly -- UAC is an originating stateful element 			   which cannot be refreshed, so the value can be			   anything			*/			/* HACK : not long enough */			myrand=rand();			c=t->md5;			size=MD5_LEN;			memset(c, '0', size );			int2reverse_hex( &c, &size, myrand );		}	}}static void inline init_branches(struct cell *t){	unsigned int i;	struct ua_client *uac;	for(i=0;i<MAX_BRANCHES;i++)	{		uac=&t->uac[i];		uac->request.my_T = t;		uac->request.branch = i;#ifdef EXTRA_DEBUG		uac->request.fr_timer.tg = TG_FR;		uac->request.retr_timer.tg = TG_RT;#endif		uac->local_cancel=uac->request;	}}struct cell*  build_cell( struct sip_msg* p_msg ){	struct cell* new_cell;	int          sip_msg_len;	struct usr_avp **old;	/* allocs a new cell */	new_cell = (struct cell*)shm_malloc( sizeof( struct cell ) );	if  ( !new_cell ) {		ser_error=E_OUT_OF_MEM;		return NULL;	}	/* filling with 0 */	memset( new_cell, 0, sizeof( struct cell ) );	/* UAS */#ifdef EXTRA_DEBUG	new_cell->uas.response.retr_timer.tg=TG_RT;	new_cell->uas.response.fr_timer.tg=TG_FR;#endif	new_cell->uas.response.my_T=new_cell;	/* move the current avp list to transaction -bogdan */	old = set_avp_list( &new_cell->user_avps );	new_cell->user_avps = *old;	*old = 0;	/* enter callback, which may potentially want to parse some stuff,	 * before the request is shmem-ized */	if ( p_msg && has_reqin_tmcbs() )		run_reqin_callbacks( new_cell, p_msg, p_msg->REQ_METHOD);	if (p_msg) {		/* clean possible previous added vias/clen header or else they would 		 * get propagated in the failure routes */		free_via_clen_lump(&p_msg->add_rm);		new_cell->uas.request = sip_msg_cloner(p_msg,&sip_msg_len);		if (!new_cell->uas.request)			goto error;		new_cell->uas.end_request=((char*)new_cell->uas.request)+sip_msg_len;	}	/* UAC */	init_branches(new_cell);	new_cell->relaied_reply_branch   = -1;	/* new_cell->T_canceled = T_UNDEFINED; */#ifdef EXTRA_DEBUG	new_cell->wait_tl.tg=TG_WT;	new_cell->dele_tl.tg=TG_DEL;#endif	init_synonym_id(new_cell);	init_cell_lock(  new_cell );	return new_cell;error:	shm_free(new_cell);	/* unlink transaction AVP list and link back the global AVP list (bogdan)*/	reset_avps();	return NULL;}/* Release all the data contained by the hash table. All the aux. structures *  as sems, lists, etc, are also released */void free_hash_table(  ){	struct cell* p_cell;	struct cell* tmp_cell;	int    i;	if (tm_table)	{		/* remove the data contained by each entry */		for( i = 0 ; i<TABLE_ENTRIES; i++)		{			release_entry_lock( (tm_table->entrys)+i );			/* delete all synonyms at hash-collision-slot i */			p_cell=tm_table->entrys[i].first_cell;			for( ; p_cell; p_cell = tmp_cell )			{				tmp_cell = p_cell->next_cell;				free_cell( p_cell );			}		}		shm_free(tm_table);	}}/* */struct s_table* init_hash_table(){	int              i;	/*allocs the table*/	tm_table= (struct s_table*)shm_malloc( sizeof( struct s_table ) );	if ( !tm_table) {		LOG(L_ERR, "ERROR: init_hash_table: no shmem for TM table\n");		goto error0;	}	memset( tm_table, 0, sizeof (struct s_table ) );	/* try first allocating all the structures needed for syncing */	if (lock_initialize()==-1)		goto error1;	/* inits the entrys */	for(  i=0 ; i<TABLE_ENTRIES; i++ )	{		init_entry_lock( tm_table, (tm_table->entrys)+i );		tm_table->entrys[i].next_label = rand();	}	return  tm_table;error1:	free_hash_table( );error0:	return 0;}/*  Takes an already created cell and links it into hash table on the *  appropriate entry. */void insert_into_hash_table_unsafe( struct cell * p_cell, unsigned int _hash ){	struct entry* p_entry;	p_cell->hash_index=_hash;	/* locates the appropriate entry */	p_entry = &tm_table->entrys[ _hash ];	p_cell->label = p_entry->next_label++;	if ( p_entry->last_cell )	{		p_entry->last_cell->next_cell = p_cell;		p_cell->prev_cell = p_entry->last_cell;	} else p_entry->first_cell = p_cell;	p_entry->last_cell = p_cell;	/* update stats */	p_entry->cur_entries++;	p_entry->acc_entries++;	t_stats_new( is_local(p_cell) );}#ifdef _OBSOLETEDvoid insert_into_hash_table( struct cell * p_cell){	LOCK_HASH(p_cell->hash_index);	insert_into_hash_table_unsafe(  p_cell );	UNLOCK_HASH(p_cell->hash_index);}#endif/*  Un-link a  cell from hash_table, but the cell itself is not released */void remove_from_hash_table_unsafe( struct cell * p_cell){	struct entry*  p_entry  = &(tm_table->entrys[p_cell->hash_index]);	/* unlink the cell from entry list */	/* lock( &(p_entry->mutex) ); */	if ( p_cell->prev_cell )		p_cell->prev_cell->next_cell = p_cell->next_cell;	else		p_entry->first_cell = p_cell->next_cell;	if ( p_cell->next_cell )		p_cell->next_cell->prev_cell = p_cell->prev_cell;	else		p_entry->last_cell = p_cell->prev_cell;	/* update stats */#	ifdef EXTRA_DEBUG	if (p_entry->cur_entries==0) {		LOG(L_CRIT, "BUG: bad things happened: cur_entries=0\n");		abort();	}#	endif	p_entry->cur_entries--;	t_stats_deleted( is_local(p_cell) );	/* unlock( &(p_entry->mutex) ); */}/* print accumulated distribution of the hash table */int fifo_hash( FILE *stream, char *response_file ){	FILE *reply_file;	unsigned int i;	reply_file=open_reply_pipe(response_file);	if (reply_file==0) {		LOG(L_ERR, "ERROR: fifo_hash: file '%s' not opened\n", 			response_file);		return -1;	}	fputs( "200 ok\n\tcurrent\ttotal\n", reply_file);	for (i=0; i<TABLE_ENTRIES; i++) {		fprintf(reply_file, "%d.\t%lu\t%lu\n", 			i, tm_table->entrys[i].cur_entries ,			tm_table->entrys[i].acc_entries );	}	fclose(reply_file);	return 1;}int unixsock_hash(str* msg){	unsigned int i, ret;	ret = 0;	unixsock_reply_asciiz( "200 OK\n\tcurrent\ttotal\n");	for (i = 0; i < TABLE_ENTRIES; i++) {		if (unixsock_reply_printf("%d.\t%lu\t%lu\n", 					  i, tm_table->entrys[i].cur_entries,					  tm_table->entrys[i].acc_entries					  ) < 0) {			unixsock_reply_reset();			unixsock_reply_asciiz("500 Error while creating reply\n");			ret = -1;			break;		}	}	if (unixsock_reply_send() < 0) {		ret = -1;	}	return ret;}

⌨️ 快捷键说明

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