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

📄 exec_hf.c

📁 用来作为linux中SIP SERVER,完成VOIP网络电话中服务器的功能
💻 C
字号:
/* * * $Id: exec_hf.c,v 1.8 2004/08/24 08:58:29 janakj 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-02-28 scratchpad compatibility abandoned *  2003-01-29 scratchpad removed *  2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri) *  2003-03-19  all mallocs/frees replaced w/ pkg_malloc/pkg_free (andrei) *//* functions for creating environment variables out of a request's * header; known compact header field names are translated to * canonical form; multiple header field occurrences are merged * into a single variable * * known limitations:  * - compact header field names unknown to parser will not be translated to  *   canonical form. Thus, environment variables may have either name and  *   users have to check for both of them. * - symbols in header field names will be translated to underscore * */#include <stdlib.h>#include "../../comp_defs.h"#include "../../parser/msg_parser.h"#include "../../parser/parse_to.h"#include "../../parser/parse_via.h"#include "../../parser/parse_uri.h"#include "../../mem/mem.h"#include "../../dprint.h"#include "../../md5utils.h"#include "exec_hf.h"/* should be environment variables set by header fields ? */unsigned int setvars=1;/* insert a new header field into the structure; */static int insert_hf( struct hf_wrapper **list, struct hdr_field *hf ){	struct hf_wrapper *w; /* new wrapper */	struct hf_wrapper *i;	w=(struct hf_wrapper *)pkg_malloc(sizeof(struct hf_wrapper));	if (!w) {		LOG(L_ERR, "ERROR: insert_hf ran out of pkg mem\n");		return 0;	}	memset(w, 0, sizeof(struct hf_wrapper));	w->var_type=W_HF;w->u.hf=hf; 	w->prefix=HF_PREFIX; w->prefix_len=HF_PREFIX_LEN;	/* is there another hf of the same type?... */	for(i=*list; i; i=i->next_other) {		if (i->var_type==W_HF && i->u.hf->type==hf->type) {			/* if it is OTHER, check name too */			if (hf->type==HDR_OTHER && (hf->name.len!=i->u.hf->name.len					|| strncasecmp(i->u.hf->name.s, hf->name.s, 					   hf->name.len)!=0))				continue;			/* yes, we found a hf of same type */			w->next_same=i->next_same;			w->next_other=i->next_other;			i->next_same=w;			break;		}	}	/* ... no previous HF of the same type found */	if (i==0) {		w->next_other=*list;		*list=w;	}	return 1;}static void release_hf_struct( struct hf_wrapper *list ){	struct hf_wrapper *i, *j, *nexts, *nexto;	i=list;	while(i) {		nexto=i->next_other;		j=i->next_same;		pkg_free(i);		/* release list of same type hf */		while(j) {			nexts=j->next_same;			pkg_free(j);			j=nexts;		}		i=nexto;	}}/* if that is some of well-known header fields which have compact * form, return canonical form ... returns 1 and sets params; * 0 is returned otherwise */static int compacthdr_type2str(int type, char **hname, int *hlen ){	switch(type) {		/* HDR_CONTENT_ENCODING: 'e' -- unsupported by parser */		/* HDR_SUBJECT: 's' -- unsupported by parser */		case HDR_VIA /* v */ : 			*hname=VAR_VIA;			*hlen=VAR_VIA_LEN;			break;		case HDR_CONTENTTYPE /* c */ : 			*hname=VAR_CTYPE;			*hlen=VAR_CTYPE_LEN;			break;		case HDR_FROM /* f */: 			*hname=VAR_FROM;			*hlen=VAR_FROM_LEN;			break;		case HDR_CALLID /* i */: 			*hname=VAR_CALLID;			*hlen=VAR_CALLID_LEN;			break;		case HDR_SUPPORTED /* k */: 			*hname=VAR_SUPPORTED;			*hlen=VAR_SUPPORTED_LEN;			break;		case HDR_CONTENTLENGTH /* l */: 			*hname=VAR_CLEN;			*hlen=VAR_CLEN_LEN;			break;		case HDR_CONTACT /* m */: 			*hname=VAR_CONTACT;			*hlen=VAR_CONTACT_LEN;			break;		case HDR_TO /* t */: 			*hname=VAR_TO;			*hlen=VAR_TO_LEN;			break;		case HDR_EVENT /* o */: 			*hname=VAR_EVENT;			*hlen=VAR_EVENT_LEN;			break;		default:				return 0;	}	return 1;}static int canonize_headername(str *orig, char **hname, int *hlen ){	char *c;	int i;	*hlen=orig->len;	*hname=pkg_malloc(*hlen);	if (!*hname) {		LOG(L_ERR, "ERROR: print_vars: no mem for hname\n");		return 0;	}	for (c=orig->s, i=0; i<*hlen; i++, c++) {		/* lowercase to uppercase */		if (*c>='a' && *c<='z') 			*((*hname)+i)=*c-('a'-'A');			/* uppercase and numbers stay "as is" */		else if ((*c>='A' && *c<='Z')||(*c>='0' && *c<='9')) 			*((*hname)+i)=*c;		/* legal symbols will be translated to underscore */		else if (strchr(UNRESERVED_MARK HNV_UNRESERVED, *c)				|| (*c==ESCAPE))			*((*hname)+i)=HFN_SYMBOL;		else {			LOG(L_ERR, "ERROR: print_var unexpected char "					"'%c' in hfname %.*s\n", 					*c, *hlen, orig->s );			*((*hname)+i)=HFN_SYMBOL;		}	}	return 1;}static int print_av_var(struct hf_wrapper *w){	int env_len;	char *env;	char *c;	env_len=w->u.av.attr.len+1/*assignment*/+w->u.av.val.len+1/*ZT*/;	env=pkg_malloc(env_len);	if (!env) {		LOG(L_ERR, "ERROR: print_av_var: no malloc mem\n");		return 0;	}	c=env;	memcpy(c, w->u.av.attr.s, w->u.av.attr.len); c+=w->u.av.attr.len;	*c=EV_ASSIGN;c++;	memcpy(c, w->u.av.val.s, w->u.av.val.len);c+=w->u.av.val.len;	*c=0; /* zero termination */	w->envvar=env;	return 1;}/* creates a malloc-ed string with environment variable; returns 1 on success, * 0 on failure  */static int print_hf_var(struct hf_wrapper *w, int offset){	char *hname;	int hlen;	short canonical;	char *envvar;	int envvar_len;	struct hf_wrapper *wi;	char *c;	/* make -Wall happy */	hname=0;hlen=0;envvar=0;	/* Make sure header names with possible compact forms	 * will be printed canonically	 */	canonical=compacthdr_type2str(w->u.hf->type, &hname, &hlen);	/* header field has not been made canonical using a table;	 * do it now by uppercasing header-field name */	if (!canonical) {		if (!canonize_headername(&w->u.hf->name, &hname, &hlen)) {			LOG(L_ERR, "ERROR: print_hf_var: canonize_hn error\n");			return 0;		}	} 	/* now we have a header name, let us generate the var */	envvar_len=w->u.hf->body.len;	for(wi=w->next_same; wi; wi=wi->next_same) { /* other values, separated */		envvar_len+=1 /* separator */ + wi->u.hf->body.len;	}	envvar=pkg_malloc(w->prefix_len+hlen+1/*assignment*/+envvar_len+1/*ZT*/);	if (!envvar) {		LOG(L_ERR, "ERROR: print_var: no envvar mem\n");		goto error00;	}	memcpy(envvar, w->prefix, w->prefix_len); c=envvar+w->prefix_len;	memcpy(c, hname, hlen ); c+=hlen;	*c=EV_ASSIGN;c++;	memcpy(c, w->u.hf->body.s+offset, w->u.hf->body.len );	c+=w->u.hf->body.len;	for (wi=w->next_same; wi; wi=wi->next_same) {		*c=HF_SEPARATOR;c++;		memcpy(c, wi->u.hf->body.s+offset, wi->u.hf->body.len );		c+=wi->u.hf->body.len;	}	*c=0; /* zero termination */	DBG("DEBUG: print_var: %s\n", envvar );		w->envvar=envvar;	if (!canonical) pkg_free(hname);	return 1;error00:	if (!canonical) pkg_free(hname);	return 0;}static int print_var(struct hf_wrapper *w, int offset){	switch(w->var_type) {		case W_HF: 			return print_hf_var(w, offset);		case W_AV: 			return print_av_var(w);		default:		   	LOG(L_CRIT, "BUG: print_var: unknown type: %d\n",					w->var_type );			return 0;	}}static void release_vars(struct hf_wrapper *list) {	while(list) {		if (list->envvar) {			pkg_free(list->envvar);			list->envvar=0;		}		list=list->next_other;	}}/* create ordered HF structure in pkg memory */static int build_hf_struct(struct sip_msg *msg, struct hf_wrapper **list){	struct hdr_field *h;	*list=0;	/* create ordered header-field structure */	for (h=msg->headers; h; h=h->next) {		if (!insert_hf(list,h)) {			LOG(L_ERR, "ERROR: build_hf_struct: insert_hf failed\n");			goto error00;		}	}	return 1;error00:	release_hf_struct(*list);	*list=0;	return 0;}/* create env vars in malloc memory */static int create_vars(struct hf_wrapper *list, int offset){	int var_cnt;	struct hf_wrapper *w;	/* create variables now */	var_cnt=0;	for(w=list;w;w=w->next_other) {		if (!print_var(w, offset)) {			LOG(L_ERR, "ERROR: build_hf_struct: create_vars failed\n");			return 0;		}		var_cnt++;	}	return var_cnt;}environment_t *replace_env(struct hf_wrapper *list){	int var_cnt;	char **cp;	struct hf_wrapper *w;	char **new_env;	int i;	environment_t *backup_env;	backup_env=(environment_t *)pkg_malloc(sizeof(environment_t));	if (!backup_env) {		LOG(L_ERR, "ERROR: replace_env: no mem for backup env\n");		return 0;	}	/* count length of current env list */	var_cnt=0;	for (cp=environ; *cp; cp++) var_cnt++;	backup_env->old_cnt=var_cnt;	/* count length of our extensions */	for(w=list;w;w=w->next_other) var_cnt++;	new_env=pkg_malloc((var_cnt+1)*sizeof(char *));	if (!new_env) {		LOG(L_ERR, "ERROR: replace_env: no mem\n");		return 0;	}	/* put all var pointers into new environment */	i=0;	for (cp=environ; *cp; cp++) { /* replicate old env */		new_env[i]=*cp;		i++;	}	for (w=list;w;w=w->next_other) { /* append new env */		new_env[i]=w->envvar;		i++;	}	new_env[i]=0; /* zero termination */	/* install new environment */	backup_env->env=environ;	environ=new_env;	/* return previous environment */	return backup_env;}void unset_env(environment_t *backup_env){	char **cur_env, **cur_env0;	int i;	/* switch-over to backup environment */	cur_env0=cur_env=environ;	environ=backup_env->env;	i=0;	/* release environment */	while(*cur_env) {		/* leave previously existing vars alone */		if (i>=backup_env->old_cnt) {			pkg_free(*cur_env);		}		cur_env++;		i++;	}	pkg_free(cur_env0);	pkg_free(backup_env);}static int append_var(char *name, char *value, int len, struct hf_wrapper **list){	struct hf_wrapper *w;	w=(struct hf_wrapper *)pkg_malloc(sizeof(struct hf_wrapper));	if (!w) {		LOG(L_ERR, "ERROR: append_var ran out of mem\n");		return 0;	}	memset(w, 0, sizeof(struct hf_wrapper)); 	w->var_type=W_AV;	w->u.av.attr.s=name;	w->u.av.attr.len=strlen(name);	w->u.av.val.s=value;	/* NULL strings considered empty, if len unknown, calculate it now */	w->u.av.val.len= value==0?0:(len==0? strlen(value) : len);	w->next_other=*list;	*list=w;	return 1;}static int append_fixed_vars(struct sip_msg *msg, struct hf_wrapper **list){	static char tid[MD5_LEN];	str *uri;	struct sip_uri parsed_uri, oparsed_uri;	char *val;	int val_len;	/* source ip */	if (!append_var(EV_SRCIP, ip_addr2a(&msg->rcv.src_ip), 0, list)) {		LOG(L_ERR, "ERROR: append_var SRCIP failed \n");		return 0;	}	/* request URI */	uri=msg->new_uri.s && msg->new_uri.len ? 		&msg->new_uri : &msg->first_line.u.request.uri;	if (!append_var(EV_RURI, uri->s, uri->len, list )) {		LOG(L_ERR, "ERROR: append_var URI failed\n");		return 0;	}	/* userpart of request URI */	if (parse_uri(uri->s, uri->len, &parsed_uri)<0) {		LOG(L_WARN, "WARNING: append_var: URI not parsed\n");	} else {		if (!append_var(EV_USER, parsed_uri.user.s, 					parsed_uri.user.len, list)) {			LOG(L_ERR, "ERROR: append_var USER failed\n");			goto error;		}	}	/* original URI */	if (!append_var(EV_ORURI, msg->first_line.u.request.uri.s,				msg->first_line.u.request.uri.len, list)) {		LOG(L_ERR, "ERROR: append_var O-URI failed\n");		goto error;	}	/* userpart of request URI */	if (parse_uri(msg->first_line.u.request.uri.s, 				msg->first_line.u.request.uri.len, 				&oparsed_uri)<0) {		LOG(L_WARN, "WARNING: append_var: orig URI not parsed\n");	} else {		if (!append_var(EV_OUSER, oparsed_uri.user.s, 					oparsed_uri.user.len, list)) {			LOG(L_ERR, "ERROR: append_var OUSER failed\n");			goto error;		}	}	/* tid, transaction id == via/branch */	if (!char_msg_val(msg, tid)) {		LOG(L_WARN, "WARNING: no tid can be determined\n");		val=0; val_len=0;	} else {		val=tid;val_len=MD5_LEN;	}	if (!append_var(EV_TID, val,val_len, list)) {		LOG(L_ERR, "ERROR: append_var TID failed\n");		goto error;	}	/* did, dialogue id == To-tag */	if (!(msg->to && get_to(msg) ))  {		LOG(L_ERR, "ERROR: append_var: no to-tag\n");		val=0; val_len=0;	} else {		val=get_to(msg)->tag_value.s;		val_len=get_to(msg)->tag_value.len;	}	if (!append_var(EV_DID, val, val_len, list)) {		LOG(L_ERR, "ERROR: append_var DID failed\n");		goto error;	}	return 1;error:	return 0;}environment_t *set_env(struct sip_msg *msg){	struct hf_wrapper *hf_list;	environment_t *backup_env;	/* parse all so that we can pass all header fields to script */	if (parse_headers(msg, HDR_EOH, 0)==-1) {		LOG(L_ERR, "ERROR: set_env: parsing failed\n");		return 0;	}	hf_list=0;	/* create a temporary structure with ordered header fields	 * and create environment variables out of it */	if (!build_hf_struct(msg, &hf_list)) {		LOG(L_ERR, "ERROR: set_env: build_hf_struct failed\n");		return 0;	}	if (!append_fixed_vars(msg, &hf_list)) {		LOG(L_ERR, "ERROR: ser_env: append_fixed_vars failed\n");		goto error01;	}	/* create now the strings for environment variables */	if (!create_vars(hf_list, 0)) {		LOG(L_ERR, "ERROR: set_env: create_vars failed\n");		goto error00;	}	/* install the variables in current environment */	backup_env=replace_env(hf_list);	if (!backup_env) {		LOG(L_ERR, "ERROR: set_env: replace_env failed\n");		goto error00;	}	/* release the ordered HF structure -- we only need the vars now */	release_hf_struct(hf_list);	return backup_env;error00:	release_vars(hf_list); /* release variables */error01:	release_hf_struct(hf_list); /* release temporary ordered HF struct */	return 0;}

⌨️ 快捷键说明

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