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

📄 cpl_run.c

📁 用来作为linux中SIP SERVER,完成VOIP网络电话中服务器的功能
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * $Id: cpl_run.c,v 1.37.2.2 2005/07/20 17:11:51 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-01-23 : created (bogdan) * 2003-09-11 : build_lump_rpl() merged into add_lump_rpl() (bogdan) * 2004-06-14 : all global variables merged into cpl_env and cpl_fct; *              append_branches param added to lookup node (bogdan) * 2004-06-14 : flag CPL_IS_STATEFUL is set now immediately after the  *              transaction is created (bogdan)*/#include <stdio.h>#include <string.h>#include <time.h>#include <stdlib.h>#include "../../mem/mem.h"#include "../../mem/shm_mem.h"#include "../../str.h"#include "../../dprint.h"#include "../../parser/msg_parser.h"#include "../../data_lump_rpl.h"#include "../tm/tm_load.h"#include "../usrloc/usrloc.h"#include "CPL_tree.h"#include "loc_set.h"#include "cpl_utils.h"#include "cpl_nonsig.h"#include "cpl_sig.h"#include "cpl_env.h"#include "cpl_run.h"#define EO_SCRIPT            ((char*)0xffffffff)#define DEFAULT_ACTION       ((char*)0xfffffffe)#define CPL_SCRIPT_ERROR     ((char*)0xfffffffd)#define CPL_RUNTIME_ERROR    ((char*)0xfffffffc)#define CPL_TO_CONTINUE      ((char*)0xfffffffb)#define HDR_NOT_FOUND        ((char*)0xffffffff)#define UNDEF_CHAR           (0xff)#define check_overflow_by_ptr(_ptr_,_intr_,_error_) \	do {\		if ( (char*)(_ptr_)>(_intr_)->script.len+(_intr_)->script.s ) {\			LOG(L_ERR,"ERROR:cpl_c: overflow detected ip=%p ptr=%p in "\			"func. %s, line %d\n",(_intr_)->ip,_ptr_,__FILE__,__LINE__);\			goto _error_; \		} \	}while(0)#define check_overflow_by_offset(_len_,_intr_,_error_) \	do {\		if ( (char*)((_intr_)->ip+(_len_)) > \		(_intr_)->script.len+(_intr_)->script.s ) {\			LOG(L_ERR,"ERROR:cpl_c: overflow detected ip=%p offset=%d in "\			"func. %s, line %d\n",(_intr_)->ip,_len_,__FILE__,__LINE__);\			goto _error_; \		} \	}while(0)#define get_first_child(_node_) \	((NR_OF_KIDS(_node_)==0)?DEFAULT_ACTION:(_node_)+KID_OFFSET(_node_,0))#define get_basic_attr(_p_,_code_,_n_,_intr_,_error_) \	do{\		check_overflow_by_ptr( (_p_)+BASIC_ATTR_SIZE, _intr_, _error_);\		_code_ = ntohs( *((unsigned short*)(_p_)) );\		_n_ =  ntohs( *((unsigned short*)((_p_)+2)) );\		(_p_) += 4;\	}while(0)#define get_str_attr(_p_,_s_,_len_,_intr_,_error_,_FIXUP_) \	do{\		if ( ((int)(_len_))-(_FIXUP_)<=0 ) {\			LOG(L_ERR,"ERROR:cpl_c:%s:%d: attribute is an empty string\n",\				__FILE__,__LINE__);\			goto _error_; \		} else {\			check_overflow_by_ptr( (_p_)+(_len_), _intr_, _error_);\			_s_ = _p_;\			(_p_) += (_len_) + 1*(((_len_)&0x0001)==1);\			(_len_) -= (_FIXUP_);\		}\	}while(0)struct cpl_interpreter* new_cpl_interpreter( struct sip_msg *msg, str *script){	struct cpl_interpreter *intr = 0;	intr = (struct cpl_interpreter*)shm_malloc(sizeof(struct cpl_interpreter));	if (!intr) {		LOG(L_ERR,"ERROR:build_cpl_interpreter: no more free memory!\n");		goto error;	}	memset( intr, 0, sizeof(struct cpl_interpreter));	/* init the interpreter*/	intr->script.s = script->s;	intr->script.len = script->len;	intr->recv_time = time(0);	intr->ip = script->s;	intr->msg = msg;	/* check the beginning of the script */	if ( NODE_TYPE(intr->ip)!=CPL_NODE ) {		LOG(L_ERR,"ERROR:build_cpl_interpreter: first node is not CPL!!\n");		goto error;	}	return intr;error:	return 0;}void free_cpl_interpreter(struct cpl_interpreter *intr){	if (intr) {		empty_location_set( &(intr->loc_set) );		if (intr->script.s)			shm_free( intr->script.s);		if (intr->user.s)			shm_free(intr->user.s);		if (intr->flags&CPL_RURI_DUPLICATED)			shm_free(intr->ruri);		if (intr->flags&CPL_TO_DUPLICATED)			shm_free(intr->to);		if (intr->flags&CPL_FROM_DUPLICATED)			shm_free(intr->from);		if (intr->flags&CPL_SUBJECT_DUPLICATED)			shm_free(intr->subject);		if (intr->flags&CPL_ORGANIZATION_DUPLICATED)			shm_free(intr->organization);		if (intr->flags&CPL_USERAGENT_DUPLICATED)			shm_free(intr->user_agent);		if (intr->flags&CPL_ACCEPTLANG_DUPLICATED)			shm_free(intr->accept_language);		if (intr->flags&CPL_PRIORITY_DUPLICATED)			shm_free(intr->priority);		shm_free(intr);	}}/* UPDATED + CHECKED */static inline char *run_cpl_node( struct cpl_interpreter *intr ){	char *kid;	unsigned char start;	int i;	start = (intr->flags&CPL_RUN_INCOMING)?INCOMING_NODE:OUTGOING_NODE;	/* look for the starting node (incoming or outgoing) */	for(i=0;i<NR_OF_KIDS(intr->ip);i++) {		kid= intr->ip + KID_OFFSET(intr->ip,i);		if ( NODE_TYPE(kid)==start ) {			return get_first_child(kid);		} else		if (NODE_TYPE(kid)==SUBACTION_NODE ||		NODE_TYPE(kid)==ANCILLARY_NODE ||		NODE_TYPE(kid)==INCOMING_NODE  ||		NODE_TYPE(kid)==OUTGOING_NODE ) {			continue;		} else {			LOG(L_ERR,"ERROR:cpl_c:run_cpl_node: unknown child type (%d) "				"for CPL node!!\n",NODE_TYPE(kid));			return CPL_SCRIPT_ERROR;		}	}	DBG("DEBUG:cpl_c:run_cpl_node: CPL node has no %d subnode -> default\n",		start);	return DEFAULT_ACTION;}/* UPDATED + CHECKED */static inline char *run_lookup( struct cpl_interpreter *intr ){	unsigned short attr_name;	unsigned short n;	unsigned char  clear;	char *p;	char *kid;	char *failure_kid = 0;	char *success_kid = 0;	char *notfound_kid = 0;	int  i;	time_t      tc;	urecord_t*  r;	ucontact_t* contact;	clear = NO_VAL;	/* check the params */	for( i=NR_OF_ATTR(intr->ip),p=ATTR_PTR(intr->ip) ; i>0 ; i-- ) {		get_basic_attr(p,attr_name,n,intr,script_error);		switch (attr_name) {			case CLEAR_ATTR:				if (n!=YES_VAL && n!=NO_VAL)					LOG(L_WARN,"WARNING:run_lookup: invalid value (%u) found"						" for param. CLEAR in LOOKUP node -> using "						"default (%u)!\n",n,clear);				else					clear = n;				break;			default:				LOG(L_ERR,"ERROR:run_lookup: unknown attribute (%d) in "					"LOOKUP node\n",attr_name);				goto script_error;		}	}	/* check the kids */	for( i=0 ; i<NR_OF_KIDS(intr->ip) ; i++ ) {		kid = intr->ip + KID_OFFSET(intr->ip,i);		check_overflow_by_ptr( kid+SIMPLE_NODE_SIZE(kid), intr, script_error);		switch ( NODE_TYPE(kid) ) {			case SUCCESS_NODE :				success_kid = kid;				break;			case NOTFOUND_NODE:				notfound_kid = kid;				break;			case FAILURE_NODE:				failure_kid = kid;				break;			default:				LOG(L_ERR,"ERROR:run_lookup: unknown output node type"					" (%d) for LOOKUP node\n",NODE_TYPE(kid));				goto script_error;		}	}	kid = failure_kid;	if (cpl_env.lu_domain) {		/* fetch user's contacts via usrloc */		tc = time(0);		cpl_fct.ulb.lock_udomain( cpl_env.lu_domain );		i = cpl_fct.ulb.get_urecord( cpl_env.lu_domain, &intr->user, &r);		if (i < 0) {			/* failure */			LOG(L_ERR, "ERROR:run_lookup: Error while querying usrloc\n");			cpl_fct.ulb.unlock_udomain( cpl_env.lu_domain );		} else if (i > 0) {			/* not found */			DBG("DBG:cpl-c:run_lookup: '%.*s' Not found in usrloc\n",				intr->user.len, intr->user.s);			cpl_fct.ulb.unlock_udomain( cpl_env.lu_domain );			kid = notfound_kid;		} else {			contact = r->contacts;			/* skip expired contacts */			while (contact && contact->expires<=tc)				contact = contact->next;			/* any contacts left? */			if (contact) {				/* clear loc set if requested */				if (clear)					empty_location_set( &(intr->loc_set) );				/* start adding locations to set */				do {					DBG("DBG:cpl-c:run_lookup: adding <%.*s>q=%d\n",						contact->c.len,contact->c.s,(int)(10*contact->q));					if (add_location( &(intr->loc_set), &contact->c,					(int)(10*contact->q),					CPL_LOC_DUPL|((contact->flags & FL_NAT)*CPL_LOC_NATED)					)==-1) {						LOG(L_ERR,"ERROR:cpl-c:run_lookup: unable to add "							"location to set :-(\n");						cpl_fct.ulb.unlock_udomain( cpl_env.lu_domain );						goto runtime_error;					}					contact = contact->next;				}while( contact && cpl_env.lu_append_branches);				/* set the flag for modifying the location set */				intr->flags |= CPL_LOC_SET_MODIFIED;				/* we found a valid contact */				kid = success_kid;			} else {				/* no valid contact found */				kid = notfound_kid;			}			cpl_fct.ulb.unlock_udomain( cpl_env.lu_domain );		}	}	if (kid)		return get_first_child(kid);	return DEFAULT_ACTION;runtime_error:	return CPL_RUNTIME_ERROR;script_error:	return CPL_SCRIPT_ERROR;}/* UPDATED + CHECKED */static inline char *run_location( struct cpl_interpreter *intr ){	unsigned short attr_name;	unsigned short n;	char  *p;	unsigned char  prio;	unsigned char  clear;	str url;	int i;	clear = NO_VAL;	prio = 10;	url.s = (char*)UNDEF_CHAR;	url.len = 0; /* fixes gcc 4.0 warning */	/* sanity check */	if (NR_OF_KIDS(intr->ip)>1) {		LOG(L_ERR,"ERROR:run_location: LOCATION node suppose to have max "			"one child, not %d!\n",NR_OF_KIDS(intr->ip));		goto script_error;	}	for( i=NR_OF_ATTR(intr->ip),p=ATTR_PTR(intr->ip) ; i>0 ; i-- ) {		get_basic_attr(p,attr_name,n,intr,script_error);		switch (attr_name) {			case URL_ATTR:				url.len = n;				get_str_attr( p, url.s, url.len, intr, script_error,1);				break;			case PRIORITY_ATTR:				if ( n>10)					LOG(L_WARN,"WARNING:run_location: invalid value (%u) found"						" for param. PRIORITY in LOCATION node -> using "						"default (%u)!\n",n,prio);				else					prio = n;				break;			case CLEAR_ATTR:				if (n!=YES_VAL && n!=NO_VAL)					LOG(L_WARN,"WARNING:run_location: invalid value (%u) found"						" for param. CLEAR in LOCATION node -> using "						"default (%u)!\n",n,clear);				else					clear = n;				break;			default:				LOG(L_ERR,"ERROR:run_location: unknown attribute (%d) in "					"LOCATION node\n",attr_name);				goto script_error;		}	}	if (url.s==(char*)UNDEF_CHAR) {		LOG(L_ERR,"ERROR:run_location: param. URL missing in LOCATION node\n");		goto script_error;	}	if (clear)		empty_location_set( &(intr->loc_set) );	if (add_location( &(intr->loc_set), &url, prio, 0/*no dup*/ )==-1) {		LOG(L_ERR,"ERROR:run_location: unable to add location to set :-(\n");		goto runtime_error;	}	/* set the flag for modifying the location set */	intr->flags |= CPL_LOC_SET_MODIFIED;	return get_first_child(intr->ip);runtime_error:	return CPL_RUNTIME_ERROR;script_error:	return CPL_SCRIPT_ERROR;}/* UPDATED + CHECKED */static inline char *run_remove_location( struct cpl_interpreter *intr ){	unsigned short attr_name;	unsigned short n;	char *p;	str url;	int i;	url.s = (char*)UNDEF_CHAR;	/* sanity check */	if (NR_OF_KIDS(intr->ip)>1) {		LOG(L_ERR,"ERROR:cpl_c:run_remove_location: REMOVE_LOCATION node "			"suppose to have max one child, not %d!\n",			NR_OF_KIDS(intr->ip));		goto script_error;	}	/* dirty hack to speed things up in when loc set is already empty */	if (intr->loc_set==0)		goto done;	for( i=NR_OF_ATTR(intr->ip),p=ATTR_PTR(intr->ip) ; i>0 ; i-- ) {		get_basic_attr(p,attr_name,n,intr,script_error);		switch (attr_name) {			case LOCATION_ATTR:				url.len = n;				get_str_attr( p, url.s, url.len, intr, script_error,1);				break;			default:				LOG(L_ERR,"ERROR:run_remove_location: unknown attribute "					"(%d) in REMOVE_LOCATION node\n",attr_name);				goto script_error;		}	}	if (url.s==(char*)UNDEF_CHAR) {		DBG("DEBUG:run_remove_location: remove all locs from loc_set\n");		empty_location_set( &(intr->loc_set) );	} else {		remove_location( &(intr->loc_set), url.s, url.len );	}	/* set the flag for modifying the location set */	intr->flags |= CPL_LOC_SET_MODIFIED;done:	return get_first_child(intr->ip);script_error:	return CPL_SCRIPT_ERROR;}/* UPDATED + CHECKED */static inline char *run_sub( struct cpl_interpreter *intr ){	char  *p;	unsigned short offset;	unsigned short attr_name;	int i;	/* sanity check */	if (NR_OF_KIDS(intr->ip)!=0) {		LOG(L_ERR,"ERROR:cpl_c:run_sub: SUB node doesn't suppose to have any "			"sub-nodes. Found %d!\n",NR_OF_KIDS(intr->ip));		goto script_error;	}	/* check the number of attr */	i = NR_OF_ATTR( intr->ip );	if (i!=1) {		LOG(L_ERR,"ERROR:cpl_c:run_sub: incorrect nr. of attr. %d (<>1) in "			"SUB node\n",i);		goto script_error;	}	/* get attr's name */	p = ATTR_PTR(intr->ip);	get_basic_attr( p, attr_name, offset, intr, script_error);	if (attr_name!=REF_ATTR) {		LOG(L_ERR,"ERROR:cpl_c:run_sub: invalid attr. %d (expected %d)in "			"SUB node\n", attr_name, REF_ATTR);		goto script_error;	}	/* make the jump */	p = intr->ip - offset;	/* check the destination pointer -> are we still inside the buffer ;-) */	if (((char*)p)<intr->script.s) {		LOG(L_ERR,"ERROR:cpl_c:run_sub: jump offset lower than the script "			"beginning -> underflow!\n");		goto script_error;	}	check_overflow_by_ptr( p+SIMPLE_NODE_SIZE(intr->ip), intr, script_error);	/* check to see if we hit a subaction node */	if ( NODE_TYPE(p)!=SUBACTION_NODE ) {		LOG(L_ERR,"ERROR:cpl_c:run_sub: sub. jump hit a nonsubaction node!\n");		goto script_error;	}	if ( NR_OF_ATTR(p)!=0 ) {		LOG(L_ERR,"ERROR:cpl_c:run_sub: invalid subaction node reached "		"(attrs=%d); expected (0)!\n",NR_OF_ATTR(p));		goto script_error;	}	return get_first_child(p);script_error:	return CPL_SCRIPT_ERROR;}/* UPDATED + CHECKED */static inline char *run_reject( struct cpl_interpreter *intr ){	unsigned short attr_name;	unsigned short status;	unsigned short n;	char *reason_s;	char *p;	int i;	reason_s = (char*)UNDEF_CHAR;	status = UNDEF_CHAR;	/* sanity check */	if (NR_OF_KIDS(intr->ip)!=0) {		LOG(L_ERR,"ERROR:cpl_c:run_reject: REJECT node doesn't suppose to have "			"any sub-nodes. Found %d!\n",NR_OF_KIDS(intr->ip));		goto script_error;

⌨️ 快捷键说明

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