📄 t_fifo.c
字号:
/* * $Id: t_fifo.c,v 1.15.2.7 2005/08/29 14:27:15 rco Exp $ * * transaction maintenance functions * * 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: * ------- * 2004-02-23 created by splitting it from t_funcs (bogdan) * 2004-11-15 t_write_xxx can print whatever avp/hdr */#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <errno.h>#include <string.h>#include <sys/uio.h>#include <unistd.h>#include <fcntl.h>#include <sys/un.h>#include <ctype.h>#include <string.h>#include "../../str.h"#include "../../ut.h"#include "../../dprint.h"#include "../../mem/mem.h"#include "../../usr_avp.h"#include "../../parser/parser_f.h"#include "../../parser/parse_from.h"#include "../../parser/parse_rr.h"#include "../../parser/parse_nameaddr.h"#include "../../parser/parse_hname2.h"#include "../../parser/contact/parse_contact.h"#include "../../tsend.h"#include "t_lookup.h"#include "t_fwd.h"#include "t_fifo.h"/* AF_LOCAL is not defined on solaris */#if !defined(AF_LOCAL)#define AF_LOCAL AF_UNIX#endif#if !defined(PF_LOCAL)#define PF_LOCAL PF_UNIX#endif/* solaris doesn't have SUN_LEN */#ifndef SUN_LEN#define SUN_LEN(sa) ( strlen((sa)->sun_path) + \ (size_t)(((struct sockaddr_un*)0)->sun_path) )#endifint tm_unix_tx_timeout = 2; /* Default is 2 seconds */#define TWRITE_PARAMS 20#define TWRITE_VERSION_S "0.3"#define TWRITE_VERSION_LEN (sizeof(TWRITE_VERSION_S)-1)#define eol_line_s(_i_) ( iov_lines_eol[2*(_i_)].iov_base )#define eol_line_len(_i_) ( iov_lines_eol[2*(_i_)].iov_len )#define eol_line(_i_,_s_) { eol_line_s(_i_) = (_s_).s; \ eol_line_len(_i_) = (_s_).len; }#define IDBUF_LEN 128#define ROUTE_BUFFER_MAX 512#define APPEND_BUFFER_MAX 4096#define CMD_BUFFER_MAX 128#define append_str(_dest,_src,_len) \ do{ \ memcpy( (_dest) , (_src) , (_len) );\ (_dest) += (_len) ;\ }while(0);#define append_chr(_dest,_c) \ *((_dest)++) = _c;#define copy_route(s,len,rs,rlen) \ do {\ if(rlen+len+3 >= ROUTE_BUFFER_MAX){\ LOG(L_ERR,"vm: buffer overflow while copying new route\n");\ goto error;\ }\ if(len){\ append_chr(s,','); len++;\ }\ append_chr(s,'<');len++;\ append_str(s,rs,rlen);\ len += rlen; \ append_chr(s,'>');len++;\ } while(0)static struct iovec iov_lines_eol[2*TWRITE_PARAMS];static struct iovec eol={"\n",1};static int sock;struct hdr_avp { str title; int type; str sval; int ival; struct hdr_avp *next;};struct tw_append { str name; int add_body; struct hdr_avp *elems; struct tw_append *next;};struct tw_info { str action; struct tw_append *append;};#define ELEM_TYPE_AVP "avp"#define ELEM_TYPE_AVP_LEN (sizeof(ELEM_TYPE_AVP)-1)#define ELEM_TYPE_HDR "hdr"#define ELEM_TYPE_HDR_LEN (sizeof(ELEM_TYPE_HDR)-1)#define ELEM_TYPE_MSG "msg"#define ELEM_TYPE_MSG_LEN (sizeof(ELEM_TYPE_MSG)-1)#define ELEM_IS_AVP (1<<0)#define ELEM_IS_HDR (1<<1)#define ELEM_IS_MSG (1<<2)#define ELEM_VAL_BODY "body"#define ELEM_VAL_BODY_LEN (sizeof(ELEM_VAL_BODY)-1)static struct tw_append *tw_appends;static void print_tw_append( struct tw_append *append){ struct hdr_avp *ha; if (!append) return; DBG("DEBUG:tm:print_tw_append: tw_append name=<%.*s>\n", append->name.len,append->name.s); for( ha=append->elems ; ha ; ha=ha->next ) { DBG("\ttitle=<%.*s>\n",ha->title.len,ha->title.s); DBG("\t\tttype=<%d>\n",ha->type); DBG("\t\tsval=<%.*s>\n",ha->sval.len,ha->sval.s); DBG("\t\tival=<%d>\n",ha->ival); }}/* tw_append syntax: * tw_append = name:element[;element] * element = [title=]value * value = avp[avp_spec] | hdr[hdr_name] | msg[body] */int parse_tw_append( modparam_t type, void* val){ struct hdr_field hdr; struct hdr_avp *last; struct hdr_avp *ha; struct tw_append *app; int_str avp_name; char *s; char bar; str foo; int n; if (val==0 || ((char*)val)[0]==0) return 0; s = (char*)val; /* start parsing - first the name */ while( *s && isspace((int)*s) ) s++; if ( !*s || *s==':') goto parse_error; foo.s = s; while ( *s && *s!=':' && !isspace((int)*s) ) s++; if ( !*s || foo.s==s ) goto parse_error; foo.len = s - foo.s; /* parse separator */ while( *s && isspace((int)*s) ) s++; if ( !*s || *s!=':') goto parse_error; s++; while( *s && isspace((int)*s) ) s++; if ( !*s ) goto parse_error; /* check for name duplication */ for(app=tw_appends;app;app=app->next) if (app->name.len==foo.len && !strncasecmp(app->name.s,foo.s,foo.len)){ LOG(L_ERR,"ERROR:tm:parse_tw_append: duplicated tw_append name " "<%.*s>\n",foo.len,foo.s); goto error; } /* new tw_append structure */ app = (struct tw_append*)pkg_malloc( sizeof(struct tw_append) ); if (app==0) { LOG(L_ERR,"ERROR:tm:parse_tw_append: no more pkg memory\n"); goto error; } app->name.s = (char*)pkg_malloc( foo.len+1 ); if (app->name.s==0) { LOG(L_ERR,"ERROR:tm:parse_tw_append: no more pkg memory\n"); goto error; } memcpy( app->name.s, foo.s, foo.len); app->name.len = foo.len; app->name.s[app->name.len] = 0; last = app->elems = 0; app->next = tw_appends; tw_appends = app; /* parse the elements */ while (*s) { /* parse element title or element type */ foo.s = s; while( *s && *s!='[' && *s!='=' && *s!=';' && !isspace((int)*s) ) s++; if ( !*s || foo.s==s) goto parse_error; foo.len = s - foo.s; /* new hdr_avp structure */ ha = (struct hdr_avp*)pkg_malloc( sizeof(struct hdr_avp) ); if (ha==0) { LOG(L_ERR,"ERROR:tm:parse_tw_append: no more pkg memory\n"); goto error; } memset( ha, 0, sizeof(struct hdr_avp)); if (*s!='[') { /* foo must by title or some error -> parse separator */ while( *s && isspace((int)*s) ) s++; if ( !*s || *s!='=') goto parse_error; s++; while( *s && isspace((int)*s) ) s++; if ( !*s ) goto parse_error; /* set the title */ ha->title.s = (char*)pkg_malloc( foo.len+1 ); if (ha->title.s==0) { LOG(L_ERR,"ERROR:tm:parse_tw_append: no more pkg memory\n"); goto error; } memcpy( ha->title.s, foo.s, foo.len); ha->title.len = foo.len; ha->title.s[ha->title.len] = 0; /* parse the type now */ foo.s = s; while( *s && *s!='[' && *s!=']' && *s!=';' && !isspace((int)*s) ) s++; if ( *s!='[' || foo.s==s) goto parse_error; foo.len = s - foo.s; } /* foo containes the elemet type */ if ( foo.len==ELEM_TYPE_AVP_LEN && !strncasecmp( foo.s, ELEM_TYPE_AVP, foo.len) ) { ha->type = ELEM_IS_AVP; } else if ( foo.len==ELEM_TYPE_HDR_LEN && !strncasecmp( foo.s, ELEM_TYPE_HDR, foo.len) ) { ha->type = ELEM_IS_HDR; } else if ( foo.len==ELEM_TYPE_MSG_LEN && !strncasecmp( foo.s, ELEM_TYPE_MSG, foo.len) ) { ha->type = ELEM_IS_MSG; } else { LOG(L_ERR,"ERROR:tm:parse_tw_append: unknown type <%.*s>\n", foo.len, foo.s); goto error; } /* parse the element name */ s++; foo.s = s; while( *s && *s!=']' && *s!=';' && !isspace((int)*s) ) s++; if ( *s!=']' || foo.s==s ) goto parse_error; foo.len = s - foo.s; s++; /* process and optimize the element name */ if (ha->type==ELEM_IS_AVP) { /* element is AVP */ if ( parse_avp_spec( &foo, &n, &avp_name)!=0 ) { LOG(L_ERR,"ERROR:tm:parse_tw_append: bad alias spec " "<%.*s>\n",foo.len, foo.s); goto error; } if (n&AVP_NAME_STR) { /* string name */ ha->sval.s = (char*)pkg_malloc(avp_name.s->len+1); if (ha->sval.s==0) { LOG(L_ERR,"ERROR:tm:parse_tw_append: no more pkg mem\n"); goto error; } memcpy( ha->sval.s, avp_name.s->s, avp_name.s->len); ha->sval.len = avp_name.s->len; ha->sval.s[ha->sval.len] = 0; if (ha->title.s==0) ha->title = ha->sval; } else { /* ID name - if title is missing, convert the ID to * string and us it a title */ ha->ival = avp_name.n; if (ha->title.s==0) { foo.s=int2str((unsigned long)ha->ival, &foo.len); ha->title.s = (char*)pkg_malloc( n+1 ); if (ha->title.s==0) { LOG(L_ERR,"ERROR:tm:parse_tw_append: no more pkg " "memory\n"); goto error; } memcpy( ha->title.s, foo.s, foo.len); ha->title.len = foo.len; ha->title.s[ha->title.len] = 0; } } } else if (ha->type==ELEM_IS_HDR) { /* element is HDR - try to get it's coded type if defined */ bar = foo.s[foo.len]; foo.s[foo.len] = ':'; /* parse header name */ if (parse_hname2( foo.s, foo.s+foo.len+1, &hdr)==0) { LOG(L_ERR,"BUG:tm_parse_tw_append: parse header failed\n"); goto error; } foo.s[foo.len] = bar; ha->ival = hdr.type; if (hdr.type==HDR_OTHER || ha->title.s==0) { /* duplicate hdr name */ ha->sval.s = (char*)pkg_malloc(foo.len+1); if (ha->sval.s==0) { LOG(L_ERR,"ERROR:tm:parse_tw_append: no more pkg mem\n"); goto error; } memcpy( ha->sval.s, foo.s, foo.len); ha->sval.len = foo.len; ha->sval.s[ha->sval.len] = 0; if (ha->title.s==0) ha->title = ha->sval; } } else { /* element is MSG */ if ( !(foo.len==ELEM_VAL_BODY_LEN && !strncasecmp(ELEM_VAL_BODY,foo.s,foo.len)) ) { LOG(L_ERR,"ERROR:tm:parse_tw_append: unsupported value <%.*s>" " for msg type\n",foo.len,foo.s); goto error; } app->add_body = 1; pkg_free( ha ); ha = 0; } /* parse the element separator, if present */ while( *s && isspace((int)*s) ) s++; if ( *s && *s!=';') goto parse_error; if (*s==';') { s++; while( *s && isspace((int)*s) ) s++; if (!*s) goto parse_error; } /* link the element to tw_append structure */ if (ha) { if (last==0) { last = app->elems = ha; } else { last->next = ha; last = ha; } } } /* end while */ print_tw_append( app ); /* free the old string */ pkg_free(val); return 0;parse_error: LOG(L_ERR,"ERROR:tm:parse_tw_append: parse error in <%s> around " "position %ld\n", (char*)val, (long)(s-(char*)val));error: return -1;}static struct tw_append *search_tw_append(char *name, int len){ struct tw_append * app; for( app=tw_appends ; app ; app=app->next ) if (app->name.len==len && !strncasecmp(app->name.s,name,len) ) return app; return 0;}int fixup_t_write( void** param, int param_no){ struct tw_info *twi; char *s; if (param_no==2) { twi = (struct tw_info*)pkg_malloc( sizeof(struct tw_info) ); if (twi==0) { LOG(L_ERR,"ERROR:tm:fixup_t_write: no more pkg memory\n"); return E_OUT_OF_MEM; } memset( twi, 0 , sizeof(struct tw_info)); s = (char*)*param; twi->action.s = s; if ( (s=strchr(s,'/'))!=0) { twi->action.len = s - twi->action.s; if (twi->action.len==0) { LOG(L_ERR,"ERROR:tm:fixup_t_write: empty action name\n"); return E_CFG; } s++; if (*s==0) { LOG(L_ERR,"ERROR:tm:fixup_t_write: empty append name\n"); return E_CFG; } twi->append = search_tw_append( s, strlen(s)); if (twi->append==0) { LOG(L_ERR,"ERROR:tm:fixup_t_write: unknown append name " "<%s>\n",s); return E_CFG; } } else { twi->action.len = strlen(twi->action.s); } *param=(void*)twi; } return 0;}int init_twrite_sock(void){ int flags; sock = socket(PF_LOCAL, SOCK_DGRAM, 0); if (sock == -1) { LOG(L_ERR, "init_twrite_sock: Unable to create socket: %s\n", strerror(errno)); return -1; } /* Turn non-blocking mode on */ flags = fcntl(sock, F_GETFL); if (flags == -1){ LOG(L_ERR, "init_twrite_sock: fcntl failed: %s\n", strerror(errno)); close(sock); return -1; } if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) { LOG(L_ERR, "init_twrite_sock: fcntl: set non-blocking failed:" " %s\n", strerror(errno)); close(sock); return -1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -