t_fifo.c

Go to the documentation of this file.
00001 /*
00002  * $Id: t_fifo.c 5100 2008-10-21 13:24:08Z juhe $
00003  *
00004  * transaction maintenance functions
00005  *
00006  * Copyright (C) 2001-2003 FhG Fokus
00007  *
00008  * This file is part of Kamailio, a free SIP server.
00009  *
00010  * Kamailio is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version
00014  *
00015  * Kamailio is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License 
00021  * along with this program; if not, write to the Free Software 
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  *
00024  * History:
00025  * -------
00026  *  2004-02-23  created by splitting it from t_funcs (bogdan)
00027  *  2004-11-15  t_write_xxx can print whatever avp/hdr
00028  *  2005-07-14  t_write_xxx specification aligned to use pseudo-variables 
00029  *              (bogdan)
00030  */
00031 
00032 /*! \file
00033  * \brief TM :: Transaction maintenance functions
00034  *
00035  * \ingroup tm
00036  * - Module: \ref tm
00037  */
00038 
00039 #include <sys/types.h>
00040 #include <sys/stat.h>
00041 #include <fcntl.h>
00042 #include <errno.h>
00043 #include <string.h>
00044 #include <sys/uio.h>
00045 #include <unistd.h>
00046 #include <fcntl.h>
00047 #include <sys/un.h>
00048 #include <ctype.h>
00049 #include <string.h>
00050 
00051 #include "../../str.h"
00052 #include "../../ut.h"
00053 #include "../../dprint.h"
00054 #include "../../pvar.h"
00055 #include "../../mem/mem.h"
00056 #include "../../parser/parser_f.h"
00057 #include "../../parser/parse_from.h"
00058 #include "../../parser/parse_rr.h"
00059 #include "../../parser/contact/parse_contact.h"
00060 #include "../../tsend.h"
00061 #include "t_lookup.h"
00062 #include "t_fwd.h"
00063 #include "t_fifo.h"
00064 
00065 
00066 /* AF_LOCAL is not defined on solaris */
00067 #if !defined(AF_LOCAL)
00068 #define AF_LOCAL AF_UNIX
00069 #endif
00070 #if !defined(PF_LOCAL)
00071 #define PF_LOCAL PF_UNIX
00072 #endif
00073 
00074 
00075 /* solaris doesn't have SUN_LEN */
00076 #ifndef SUN_LEN
00077 #define SUN_LEN(sa)   ( strlen((sa)->sun_path) + \
00078                 (size_t)(((struct sockaddr_un*)0)->sun_path) )
00079 #endif
00080 
00081 int tm_unix_tx_timeout = 2; /*!< Default is 2 seconds */
00082 
00083 #define TWRITE_PARAMS          20
00084 #define TWRITE_VERSION_S       "0.3"
00085 #define TWRITE_VERSION_LEN     (sizeof(TWRITE_VERSION_S)-1)
00086 #define eol_line(_i_)          ( lines_eol[2*(_i_)] )
00087 
00088 #define IDBUF_LEN              128
00089 #define ROUTE_BUFFER_MAX       512
00090 #define APPEND_BUFFER_MAX      4096
00091 #define CMD_BUFFER_MAX         128
00092 
00093 #define copy_route(s,len,rs,rlen) \
00094    do {\
00095       if(rlen+len+3 >= ROUTE_BUFFER_MAX){\
00096          LM_ERR("buffer overflow while copying new route\n");\
00097          return -1;\
00098       }\
00099       if(len){\
00100          append_chr(s,','); len++;\
00101       }\
00102       append_chr(s,'<');len++;\
00103       append_str(s,rs,rlen);\
00104       len += rlen; \
00105       append_chr(s,'>');len++;\
00106    } while(0)
00107 
00108 static str   lines_eol[2*TWRITE_PARAMS];
00109 static str   eol={"\n",1};
00110 
00111 static int sock;
00112 
00113 struct append_elem {
00114    str        name;       /*!< name / title */
00115    pv_spec_t  spec;       /*!< value's spec */
00116    struct append_elem *next;
00117 };
00118 
00119 struct tw_append {
00120    str name;
00121    int add_body;
00122    struct append_elem *elems;
00123    struct tw_append   *next;
00124 };
00125 
00126 struct tw_info {
00127    str action;
00128    struct tw_append *append;
00129 };
00130 
00131 static struct tw_append *tw_appends;
00132 
00133 
00134 /*! \brief
00135  * tw_append syntax:
00136  * tw_append = name:element[;element]
00137  * element   = (title=pseudo_variable) | msg(body)
00138  */
00139 int parse_tw_append( modparam_t type, void* val)
00140 {
00141    struct append_elem *last;
00142    struct append_elem *elem;
00143    struct tw_append *app;
00144    pv_spec_t lspec;
00145    char *s;
00146    str  foo;
00147    str  bar;
00148 
00149    
00150    if (val==0 || ((char*)val)[0]==0)
00151       return 0;
00152 
00153    s = (char*)val;
00154 
00155    /* start parsing - first the name */
00156    while( *s && isspace((int)*s) )  s++;
00157    if ( !*s || *s==':')
00158       goto parse_error;
00159    foo.s = s;
00160    while ( *s && *s!=':' && !isspace((int)*s) ) s++;
00161    if ( !*s || foo.s==s )
00162       goto parse_error;
00163    foo.len = s - foo.s;
00164    /* parse separator */
00165    while( *s && isspace((int)*s) )  s++;
00166    if ( !*s || *s!=':')
00167       goto parse_error;
00168    s++;
00169 
00170    /* check for name duplication */
00171    for(app=tw_appends;app;app=app->next)
00172       if (app->name.len==foo.len && !strncasecmp(app->name.s,foo.s,foo.len)){
00173          LM_ERR("duplicated tw_append name <%.*s>\n",foo.len,foo.s);
00174          goto error;
00175       }
00176 
00177    /* new tw_append structure */
00178    app = (struct tw_append*)pkg_malloc( sizeof(struct tw_append) );
00179    if (app==0) {
00180       LM_ERR("no more pkg memory\n");
00181       goto error;
00182    }
00183 
00184    /* init the new append */
00185    app->name = foo;
00186    last = app->elems = 0;
00187 
00188    /* link the new append */
00189    app->next = tw_appends;
00190    tw_appends = app;
00191 
00192    /* parse the elements */
00193    while (*s) {
00194 
00195       /* skip white spaces */
00196       while( *s && isspace((int)*s) )  s++;
00197       if ( !*s )
00198          goto parse_error;
00199       /* parse element name */
00200       foo.s = s;
00201       while( *s && *s!='=' && *s!=';' && !isspace((int)*s) ) s++;
00202       if (foo.s==s)
00203          goto parse_error;
00204       foo.len = s - foo.s;
00205       /* skip spaces */
00206       while( *s && isspace((int)*s) )  s++;
00207       if ( *s && *s!='=' && *s!=';' )
00208          goto parse_error;
00209 
00210       /* short element (without name) ? */
00211       if (*s=='=' ) {
00212          /* skip '=' */
00213          s++;
00214 
00215          /* new append_elem structure */
00216          elem = (struct append_elem*)pkg_malloc(sizeof(struct append_elem));
00217          if (elem==0) {
00218             LM_ERR("no more pkg memory\n");
00219             goto error;
00220          }
00221          memset( elem, 0, sizeof(struct append_elem));
00222 
00223          /* set and link the element */
00224          elem->name = foo;
00225          if (last==0) {
00226             app->elems = elem;
00227          } else {
00228             last->next = elem;
00229          }
00230          last = elem;
00231 
00232          /* skip spaces */
00233          while (*s && isspace((int)*s))
00234             s++;
00235       } else {
00236          /* go back to reparse as value */
00237          s = foo.s;
00238          elem = 0;
00239       }
00240 
00241       /* get value type */
00242       bar.s = s; bar.len = strlen(bar.s);
00243       if ( (foo.s=pv_parse_spec( &bar, &lspec))==0 )
00244          goto parse_error;
00245 
00246       /* if short element....which one? */
00247       if (elem==0) {
00248          if (lspec.type!=PVT_MSG_BODY) {
00249          LM_ERR("short spec '%.*s' unknown(aceepted only body)\n",
00250                (int)(long)(foo.s-s), s);
00251             goto error;
00252          }
00253          app->add_body = 1;
00254       } else {
00255          elem->spec = lspec;
00256       }
00257 
00258       /* continue parsing*/
00259       s = foo.s;
00260 
00261       /* skip spaces */
00262       while (*s && isspace((int)*s))  s++;
00263       if (*s && *(s++)!=';')
00264          goto parse_error;
00265    }
00266 
00267    /* go throught all elements and make the names null terminated */
00268    for( elem=app->elems ; elem ; elem=elem->next)
00269       elem->name.s[elem->name.len] = 0;
00270    /* make the append name null terminated also */
00271    app->name.s[app->name.len] = 0;
00272 
00273    return 0;
00274 parse_error:
00275    LM_ERR("parse error in <%s> around position %ld(%c)\n",
00276          (char*)val, (long)(s-(char*)val),*s);
00277 error:
00278    return -1;
00279 }
00280 
00281 
00282 static struct tw_append *search_tw_append(char *name, int len)
00283 {
00284    struct tw_append * app;
00285 
00286    for( app=tw_appends ; app ; app=app->next )
00287       if (app->name.len==len && !strncasecmp(app->name.s,name,len) )
00288          return app;
00289    return 0;
00290 }
00291 
00292 
00293 int fixup_t_write( void** param, int param_no)
00294 {
00295    struct tw_info *twi;
00296    char *s;
00297 
00298    if (param_no==2) {
00299       twi = (struct tw_info*)pkg_malloc( sizeof(struct tw_info) );
00300       if (twi==0) {
00301          LM_ERR("no more pkg memory\n");
00302          return E_OUT_OF_MEM;
00303       }
00304       memset( twi, 0 , sizeof(struct tw_info));
00305       s = (char*)*param;
00306       twi->action.s = s;
00307       if ( (s=strchr(s,'/'))!=0) {
00308          twi->action.len = s - twi->action.s;
00309          if (twi->action.len==0) {
00310             LM_ERR("empty action name\n");
00311             return E_CFG;
00312          }
00313          s++;
00314          if (*s==0) {
00315             LM_ERR("empty append name\n");
00316             return E_CFG;
00317          }
00318          twi->append = search_tw_append( s, strlen(s));
00319          if (twi->append==0) {
00320             LM_ERR("unknown append name <%s>\n",s);
00321             return E_CFG;
00322          }
00323       } else {
00324          twi->action.len = strlen(twi->action.s);
00325       }
00326       *param=(void*)twi;
00327    }
00328 
00329    return 0;
00330 }
00331 
00332 
00333 
00334 int init_twrite_sock(void)
00335 {
00336    int flags;
00337 
00338    sock = socket(PF_LOCAL, SOCK_DGRAM, 0);
00339    if (sock == -1) {
00340       LM_ERR("unable to create socket: %s\n", strerror(errno));
00341       return -1;
00342    }
00343 
00344         /* Turn non-blocking mode on */
00345    flags = fcntl(sock, F_GETFL);
00346    if (flags == -1){
00347       LM_ERR("init_twrite_sock: fcntl failed: %s\n", strerror(errno));
00348       close(sock);
00349       return -1;
00350    }
00351       
00352    if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) {
00353       LM_ERR("init_twrite_sock: fcntl: set non-blocking failed:"
00354           " %s\n", strerror(errno));
00355       close(sock);
00356       return -1;
00357    }
00358    return 0;
00359 }
00360 
00361 
00362 
00363 int init_twrite_lines(void)
00364 {
00365    int i;
00366 
00367    /* init the line table */
00368    for(i=0;i<TWRITE_PARAMS;i++) {
00369       lines_eol[2*i].s = 0;
00370       lines_eol[2*i].len = 0;
00371       lines_eol[2*i+1] = eol;
00372    }
00373 
00374    /* first line is the version - fill it now */
00375    eol_line(0).s   = TWRITE_VERSION_S;
00376    eol_line(0).len = TWRITE_VERSION_LEN;
00377 
00378    return 0;
00379 }
00380 
00381 
00382 
00383 static inline int write_to_fifo(char *fifo, int cnt )
00384 {
00385    int   fd_fifo;
00386 
00387    /* open FIFO file stream */
00388    if((fd_fifo = open(fifo,O_WRONLY | O_NONBLOCK)) == -1){
00389       switch(errno){
00390          case ENXIO:
00391             LM_ERR("nobody listening on [%s] fifo for reading!\n",fifo);
00392          default:
00393             LM_ERR("failed to open [%s] fifo : %s\n", fifo,
00394                   strerror(errno));
00395       }
00396       goto error;
00397    }
00398 
00399    /* write now (unbuffered straight-down write) */
00400 repeat:
00401    if (writev(fd_fifo, (struct iovec*)(void*)lines_eol, 2*cnt)<0) {
00402       if (errno!=EINTR) {
00403          LM_ERR("writev failed: %s\n", strerror(errno));
00404          close(fd_fifo);
00405          goto error;
00406       } else {
00407          goto repeat;
00408       }
00409    }
00410    close(fd_fifo);
00411 
00412    LM_DBG("write completed\n");
00413    return 1; /* OK */
00414 
00415 error:
00416    return -1;
00417 }
00418 
00419 
00420 
00421 static inline char* add2buf(char *buf, char *end, str *name, str *value)
00422 {
00423    if (buf+name->len+value->len+2+1>=end)
00424       return 0;
00425    memcpy( buf, name->s, name->len);
00426    buf += name->len;
00427    *(buf++) = ':';
00428    *(buf++) = ' ';
00429    memcpy( buf, value->s, value->len);
00430    buf += value->len;
00431    *(buf++) = '\n';
00432    return buf;
00433 }
00434 
00435 
00436 
00437 static inline char* append2buf( char *buf, int len, struct sip_msg *req, 
00438             struct append_elem *elem)
00439 {
00440    pv_value_t value;
00441    char *end;
00442 
00443    end = buf+len;
00444 
00445    while (elem)
00446    {
00447       /* get the value */
00448       if (pv_get_spec_value(req, &elem->spec, &value)!=0)
00449       {
00450          LM_ERR("failed to get '%.*s'\n", elem->name.len,elem->name.s);
00451       }
00452 
00453       /* empty element? */
00454       if ( !(value.flags&PV_VAL_NULL) ) {
00455          /* write the value into the buffer */
00456          buf = add2buf( buf, end, &elem->name, &value.rs);
00457          if (!buf)
00458          {
00459             LM_ERR("overflow -> append exceeded %d len\n",len);
00460             return 0;
00461          }
00462       }
00463 
00464       elem = elem->next;
00465    }
00466 
00467    return buf;
00468 }
00469 
00470 /*!
00471  * \brief Assemble a message
00472  *
00473  * Assemble a message
00474  * A return code of 0 would lead to immediate script exit --
00475  * -1 return value means 'false' to script processing
00476  * \return 1 on success, -1 on errors
00477  */
00478 static int assemble_msg(struct sip_msg* msg, struct tw_info *twi)
00479 {
00480    static char     id_buf[IDBUF_LEN];
00481    static char     route_buffer[ROUTE_BUFFER_MAX];
00482    static char     append_buf[APPEND_BUFFER_MAX];
00483    static char     cmd_buf[CMD_BUFFER_MAX];
00484    static str      empty_param = {".",1};
00485    unsigned int      hash_index, label;
00486    contact_body_t*   cb=0;
00487    contact_t*        c=0;
00488    name_addr_t       na;
00489    rr_t*             record_route;
00490    struct hdr_field* p_hdr;
00491    param_hooks_t     hooks;
00492    int               l;
00493    char*             s, fproxy_lr;
00494    str               route, next_hop, append, tmp_s, body, str_uri;
00495 
00496    if(msg->first_line.type != SIP_REQUEST){
00497       LM_ERR("called for something else then a SIP request\n");
00498       return -1;
00499    }
00500 
00501    /* parse all -- we will need every header field for a UAS */
00502    if ( parse_headers(msg, HDR_EOH_F, 0)==-1) {
00503       LM_ERR("parse_headers failed\n");
00504       return -1;
00505    }
00506 
00507    /* find index and hash; (the transaction can be safely used due 
00508     * to refcounting till script completes) */
00509    if( t_get_trans_ident(msg,&hash_index,&label) == -1 ) {
00510       LM_ERR("t_get_trans_ident failed\n");
00511       return -1;
00512    }
00513 
00514     /* parse from header */
00515    if (msg->from->parsed==0 && parse_from_header(msg)<0 ) {
00516       LM_ERR("failed to parse <From:> header\n");
00517       return -1;
00518    }
00519 
00520    /* parse the RURI (doesn't make any malloc) */
00521    msg->parsed_uri_ok = 0; /* force parsing */
00522    if (parse_sip_msg_uri(msg)<0) {
00523       LM_ERR("uri has not been parsed\n");
00524       return -1;
00525    }
00526 
00527    /* parse contact header */
00528    str_uri.s = 0;
00529    str_uri.len = 0;
00530    if(msg->contact) {
00531       if (msg->contact->parsed==0 && parse_contact(msg->contact)<0) {
00532          LM_ERR("failed to parse <Contact:> header\n");
00533          return -1;
00534       }
00535       cb = (contact_body_t*)msg->contact->parsed;
00536       if(cb && (c=cb->contacts)) {
00537          str_uri = c->uri;
00538          if (find_not_quoted(&str_uri,'<')) {
00539             parse_nameaddr(&str_uri,&na);
00540             str_uri = na.uri;
00541          }
00542       }
00543    }
00544 
00545    /* str_uri is taken from caller's contact or from header
00546     * for backwards compatibility with pre-3261 (from is already parsed)*/
00547    if(!str_uri.len || !str_uri.s)
00548       str_uri = get_from(msg)->uri;
00549 
00550    /* parse Record-Route headers */
00551    route.s = s = route_buffer; route.len = 0;
00552    fproxy_lr = 0;
00553    next_hop = empty_param;
00554 
00555    p_hdr = msg->record_route;
00556    if(p_hdr) {
00557       if (p_hdr->parsed==0 && parse_rr(p_hdr)!=0 ) {
00558          LM_ERR("failed to parse 'Record-Route:' header\n");
00559          return -1;
00560       }
00561       record_route = (rr_t*)p_hdr->parsed;
00562    } else {
00563       record_route = 0;
00564    }
00565 
00566    if( record_route ) {
00567       if ( (tmp_s.s=find_not_quoted(&record_route->nameaddr.uri,';'))!=0 &&
00568       tmp_s.s+1!=record_route->nameaddr.uri.s+
00569       record_route->nameaddr.uri.len) {
00570          /* Parse all parameters */
00571          tmp_s.len = record_route->nameaddr.uri.len - (tmp_s.s-
00572             record_route->nameaddr.uri.s);
00573          if (parse_params( &tmp_s, CLASS_URI, &hooks, 
00574          &record_route->params) < 0) {
00575             LM_ERR("failed to parse record route uri params\n");
00576             return -1;
00577          }
00578          fproxy_lr = (hooks.uri.lr != 0);
00579          LM_DBG("record_route->nameaddr.uri: %.*s\n",
00580             record_route->nameaddr.uri.len,record_route->nameaddr.uri.s);
00581          if(fproxy_lr){
00582             LM_DBG("first proxy has loose routing\n");
00583             copy_route(s,route.len,record_route->nameaddr.uri.s,
00584                record_route->nameaddr.uri.len);
00585          }
00586       }
00587       for(p_hdr = p_hdr->next;p_hdr;p_hdr = p_hdr->next) {
00588          /* filter out non-RR hdr and empty hdrs */
00589          if( (p_hdr->type!=HDR_RECORDROUTE_T) || p_hdr->body.len==0)
00590             continue;
00591 
00592          if(p_hdr->parsed==0 && parse_rr(p_hdr)!=0 ){
00593             LM_ERR("failed to parse <Record-route:> header\n");
00594             return -1;
00595          }
00596          for(record_route=p_hdr->parsed; record_route;
00597             record_route=record_route->next){
00598             LM_DBG("record_route->nameaddr.uri: <%.*s>\n",
00599                record_route->nameaddr.uri.len,
00600                record_route->nameaddr.uri.s);
00601             copy_route(s,route.len,record_route->nameaddr.uri.s,
00602                record_route->nameaddr.uri.len);
00603          }
00604       }
00605 
00606       if(!fproxy_lr){
00607          copy_route(s,route.len,str_uri.s,str_uri.len);
00608          str_uri = ((rr_t*)msg->record_route->parsed)->nameaddr.uri;
00609       } else {
00610          next_hop = ((rr_t*)msg->record_route->parsed)->nameaddr.uri;
00611       }
00612    }
00613 
00614    LM_DBG("calculated route: %.*s\n",route.len,route.len ? route.s : "");
00615    LM_DBG("next r-uri: %.*s\n",str_uri.len,str_uri.len ? str_uri.s : "");
00616 
00617    if ( REQ_LINE(msg).method_value==METHOD_INVITE || 
00618    (twi->append && twi->append->add_body) ) {
00619       /* get body */
00620       if( (body.s = get_body(msg)) == 0 ){
00621          LM_ERR("get_body failed\n");
00622          return -1;
00623       }
00624       body.len = msg->len - (body.s - msg->buf);
00625    } else {
00626       body = empty_param;
00627    }
00628 
00629    /* flags & additional headers */
00630    append.s = s = append_buf;
00631    if (sizeof(flag_t)*2+12+1 >= APPEND_BUFFER_MAX) {
00632       LM_ERR("buffer overflow while copying flags\n");
00633       return -1;
00634    }
00635    append_str(s,"P-MsgFlags: ",12);
00636    l = APPEND_BUFFER_MAX - (12+1); /* include trailing `\n'*/
00637 
00638    if (int2reverse_hex(&s, &l, (int)msg->msg_flags) == -1) {
00639       LM_ERR("buffer overflow while copying optional header\n");
00640       return -1;
00641    }
00642    append_chr(s,'\n');
00643 
00644    if ( twi->append && ((s=append2buf( s, APPEND_BUFFER_MAX-(s-append.s), msg,
00645    twi->append->elems))==0) )
00646       return -1;
00647 
00648    /* body separator */
00649    append_chr(s,'.');
00650    append.len = s-append.s;
00651 
00652    eol_line(1).s = s = cmd_buf;
00653    if(twi->action.len+12 >= CMD_BUFFER_MAX){
00654       LM_ERR("buffer overflow while copying command name\n");
00655       return -1;
00656    }
00657    append_str(s,"sip_request.",12);
00658    append_str(s,twi->action.s,twi->action.len);
00659    eol_line(1).len = s-eol_line(1).s;
00660 
00661    eol_line(2)=REQ_LINE(msg).method;     /* method type */
00662    eol_line(3)=msg->parsed_uri.user;     /* user from r-uri */
00663    eol_line(4)=msg->parsed_uri.host;     /* domain */
00664 
00665    eol_line(5)=msg->rcv.bind_address->address_str; /* dst ip */
00666 
00667    eol_line(6)=msg->rcv.dst_port==SIP_PORT ?
00668          empty_param : msg->rcv.bind_address->port_no_str; /* port */
00669 
00670    /* r_uri ('Contact:' for next requests) */
00671    eol_line(7)=*GET_RURI(msg);
00672 
00673    /* r_uri for subsequent requests */
00674    eol_line(8)=str_uri.len?str_uri:empty_param;
00675 
00676    eol_line(9)=get_from(msg)->body;    /* from */
00677    eol_line(10)=msg->to->body;         /* to */
00678    eol_line(11)=msg->callid->body;     /* callid */
00679    eol_line(12)=get_from(msg)->tag_value; /* from tag */
00680    eol_line(13)=get_to(msg)->tag_value;   /* to tag */
00681    eol_line(14)=get_cseq(msg)->number; /* cseq number */
00682 
00683    eol_line(15).s=id_buf;       /* hash:label */
00684    s = int2str(hash_index, &l);
00685    if (l+1>=IDBUF_LEN) {
00686       LM_ERR("too big hash\n");
00687       return -1;
00688    }
00689    memcpy(id_buf, s, l);
00690    id_buf[l]=':';
00691    eol_line(15).len=l+1;
00692    s = int2str(label, &l);
00693    if (l+1+eol_line(15).len>=IDBUF_LEN) {
00694       LM_ERR("too big label\n");
00695       return -1;
00696    }
00697    memcpy(id_buf+eol_line(15).len, s, l);
00698    eol_line(15).len+=l;
00699 
00700    eol_line(16) = route.len ? route : empty_param;
00701    eol_line(17) = next_hop;
00702    eol_line(18) = append;
00703    eol_line(19) = body;
00704 
00705    /* success */
00706    return 1;
00707 }
00708 
00709 
00710 static int write_to_unixsock(char* sockname, int cnt)
00711 {
00712    int len, e;
00713    struct sockaddr_un dest;
00714 
00715    if (!sockname) {
00716       LM_ERR("invalid parameter\n");
00717       return E_UNSPEC;
00718    }
00719 
00720    len = strlen(sockname);
00721    if (len == 0) {
00722       LM_ERR("empty socket name\n");
00723       return -1;
00724    } else if (len > 107) {
00725       LM_ERR("socket name too long\n");
00726       return -1;
00727    }
00728 
00729    memset(&dest, 0, sizeof(dest));
00730    dest.sun_family = PF_LOCAL;
00731    memcpy(dest.sun_path, sockname, len);
00732 #ifdef HAVE_SOCKADDR_SA_LEN
00733    dest.sun_len = len;
00734 #endif
00735 
00736    e = connect(sock, (struct sockaddr*)&dest, SUN_LEN(&dest));
00737 #ifdef HAVE_CONNECT_ECONNRESET_BUG
00738    /*
00739     * Workaround for a nasty bug in BSD kernels dated back
00740     * to the Berkeley days, so that can be found in many modern
00741     * BSD-derived kernels. Workaround should be pretty harmless since
00742     * in normal conditions connect(2) can never return ECONNRESET.
00743     */
00744    if ((e == -1) && (errno == ECONNRESET))
00745       e = 0;
00746 #endif
00747    if (e == -1) {
00748       LM_ERR("failed to connect: %s\n", strerror(errno));
00749       return -1;
00750    }
00751 
00752    if (tsend_dgram_ev(sock, (struct iovec*)(void*)lines_eol, 2 * cnt,
00753    tm_unix_tx_timeout * 1000) < 0) {
00754       LM_ERR("writev failed: %s\n", strerror(errno));
00755       return -1;
00756    }
00757 
00758    return 0;
00759 }
00760 
00761 
00762 int t_write_req(struct sip_msg* msg, char* vm_fifo, char* info)
00763 {
00764    if (assemble_msg(msg, (struct tw_info*)info) < 0) {
00765       LM_ERR("failed to assemble_msg\n");
00766       return -1;
00767    }
00768       
00769    if (write_to_fifo(vm_fifo, TWRITE_PARAMS) == -1) {
00770       LM_ERR("write_to_fifo failed\n");
00771       return -1;
00772    }
00773    
00774    /* make sure that if voicemail does not initiate a reply
00775     * timely, a SIP timeout will be sent out */
00776    if (add_blind_uac() == -1) {
00777       LM_ERR("add_blind failed\n");
00778       return -1;
00779    }
00780    return 1;
00781 }
00782 
00783 
00784 int t_write_unix(struct sip_msg* msg, char* socket, char* info)
00785 {
00786    if (assemble_msg(msg, (struct tw_info*)info) < 0) {
00787       LM_ERR("failed to assemble_msg\n");
00788       return -1;
00789    }
00790 
00791    if (write_to_unixsock(socket, TWRITE_PARAMS) == -1) {
00792       LM_ERR("write_to_unixsock failed\n");
00793       return -1;
00794    }
00795 
00796    /* make sure that if voicemail does not initiate a reply
00797     * timely, a SIP timeout will be sent out */
00798    if (add_blind_uac() == -1) {
00799       LM_ERR("add_blind failed\n");
00800       return -1;
00801    }
00802    return 1;
00803 }

Generated on Thu May 24 20:00:32 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6