- added disable tcp support (-T or disable_tcp=yes in the cfg)
[sip-router] / modules / tm / uac.c
1 /*
2  * $Id$
3  *
4  * simple UAC for things such as SUBSCRIBE or SMS gateway;
5  * no authentication and other UAC features -- just send
6  * a message, retransmit and await a reply; forking is not
7  * supported during client generation, in all other places
8  * it is -- adding it should be simple
9  *
10  * Copyright (C) 2001-2003 Fhg Fokus
11  *
12  * This file is part of ser, a free SIP server.
13  *
14  * ser is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version
18  *
19  * For a license to use the ser software under conditions
20  * other than those described here, or to purchase support for this
21  * software, please contact iptel.org by e-mail at the following addresses:
22  *    info@iptel.org
23  *
24  * ser is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License 
30  * along with this program; if not, write to the Free Software 
31  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
32  *
33  * ***************************************************
34  *             IMPORTANT NOTE
35  *
36  *    All UACs but t_uac_dlg are being deprecated now
37  *    and will be removed from future versions of TM
38  *    module. Eliminate all dependancies on them asap.
39  *    For backwards compatibility (NOT RECOMMENDED)
40  *    turn off DEPRECATE_OLD_STUFF in defs.h. Similarly,
41  *    there is a new FIFO UAC.
42  *
43  * ****************************************************
44  *
45  * History:
46  * --------
47  *  2003-01-23  t_uac_dlg now uses get_out_socket (jiri)
48  *  2003-01-27  fifo:t_uac_dlg completed (jiri)
49  *  2003-01-29  scratchpad removed (jiri)
50  *  2003-02-13  t_uac, t _uac_dlg, gethfblock, uri2proxy changed to use 
51  *               proto & rb->dst (andrei)
52  *  2003-02-27  FIFO/UAC now dumps reply -- good for CTD (jiri)
53  *  2003-02-28  scratchpad compatibility abandoned (jiri)
54  *  2003-03-01  kr set through a function now (jiri)
55  *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
56  *  2003-04-02  port_no_str does not contain a leading ':' anymore (andrei)
57  *  2003-04-15  t_uac_dlg now uses get_send_socket(get_out_socket doesn't
58  *               work for tcp) (andrei)
59  *  
60  */
61
62
63 #include "../../comp_defs.h"
64 #include "defs.h"
65
66
67 #include <stdlib.h>
68 #include <sys/types.h>
69 #include <unistd.h>
70 #include <stdio.h>
71 #include <errno.h>
72 #include <sys/types.h>
73 #include <sys/stat.h>
74 #include <fcntl.h>
75 #include <signal.h>
76 #include <limits.h>
77 #include <string.h>
78 #include "../../parser/parse_from.h"
79 #include "../../parser/msg_parser.h"
80 #include "../../dprint.h"
81 #include "../../ut.h"
82 #include "../../hash_func.h"
83 #include "../../md5utils.h"
84 #include "../../mem/mem.h"
85 #include "../../fifo_server.h"
86 #include "../../error.h"
87 #include "../../pt.h"
88 #include "../../crc.h"
89 #include "t_funcs.h"
90 #include "config.h"
91 #include "sip_msg.h"
92 #include "ut.h"
93 #include "t_msgbuilder.h"
94 #include "uac.h"
95
96 /* header fields which are explicitely processed and are not copied
97  * from FIFO line-by-line
98  */
99 #define skip_hf(_hf) (((_hf)->type==HDR_FROM) || ((_hf)->type==HDR_TO) \
100         || ((_hf)->type==HDR_CALLID) || ((_hf)->type==HDR_CSEQ))
101
102 /* Call-ID has the following form: <callid_nr>-<pid>@<ip>
103  * callid_nr is initialized as a random number and continually
104  * increases; -<pid>@<ip> is kept in callid_suffix
105  */
106
107 #define CALLID_SUFFIX_LEN (1 /* - */ + 5 /* pid */ \
108         + 42 /* embedded v4inv6 address can be looong '128.' */ \
109         + 2 /* parenthessis [] */ + 1 /* ZT 0 */ \
110         + 16 /* one never knows ;-) */ )
111 #define CALLID_NR_LEN 20
112
113 /* the character which separates random from constant part */
114 #define CID_SEP '-'
115
116 /* length of FROM tags */
117 #define FROM_TAG_LEN (MD5_LEN +1 /* - */ + CRC16_LEN)
118
119 struct str_list {
120         str s;
121         struct str_list *next;
122 };
123
124 static unsigned long callid_nr;
125 static char *callid_suffix;
126 static int callid_suffix_len;
127 static int rand_len;    /* number of chars to display max rand */
128 static char callid[CALLID_NR_LEN+CALLID_SUFFIX_LEN];
129
130 static char from_tag[ FROM_TAG_LEN+1 ];
131
132
133
134 int uac_init() {
135
136         int i; 
137         unsigned long uli;
138         int rand_len_bits;
139         int rand_cnt; /* number of rands() to be long enough */
140         int rand_bits; /* length of rands() in bits */
141         str src[3];
142
143         if (RAND_MAX<TABLE_ENTRIES) {
144                 LOG(L_WARN, "Warning: uac does not spread "
145                         "accross the whole hash table\n");
146         }
147
148         /* calculate the initial call-id */
149
150         /* how many bits and chars do we need to display the 
151          * whole ULONG number */
152         for (rand_len_bits=0,uli=ULONG_MAX;uli;
153                         uli>>=1, rand_len_bits++ );
154         rand_len=rand_len_bits/4;
155         if (rand_len>CALLID_NR_LEN) {
156                 LOG(L_ERR, "ERROR: Too small callid buffer\n");
157                 return -1;
158         }
159
160         /* how long are the rand()s ? */
161         for (rand_bits=0,i=RAND_MAX;i;i>>=1,rand_bits++);
162         /* how many rands() fit in the ULONG ? */
163         rand_cnt=rand_len_bits / rand_bits;
164
165         /* now fill in the callid with as many random
166          * numbers as you can + 1 */
167         callid_nr=rand(); /* this is the + 1 */
168         while(rand_cnt) {
169                 rand_cnt--;
170                 callid_nr<<=rand_bits;
171                 callid_nr|=rand();
172         }
173         callid_suffix=callid+rand_len;
174         DBG("CALLID initialization: %lx (len=%d)\n", 
175                         callid_nr, rand_len );
176         DBG("CALLID0=%0*lx\n", rand_len, callid_nr );
177
178
179         /* calculate the initial From tag */
180
181         src[0].s="Long live SER server";
182         src[0].len=strlen(src[0].s);
183         src[1].s=sock_info[bind_idx].address_str.s;
184         src[1].len=strlen(src[1].s);
185         src[2].s=sock_info[bind_idx].port_no_str.s;
186         src[2].len=strlen(src[2].s);
187
188         MDStringArray( from_tag, src, 3 );
189         from_tag[MD5_LEN]=CID_SEP;
190
191         return 1;
192 }
193
194
195 int uac_child_init( int rank ) 
196 {
197         callid_suffix_len=snprintf(callid_suffix,CALLID_SUFFIX_LEN,
198                         "%c%d@%.*s", CID_SEP, my_pid(), 
199                         sock_info[bind_idx].address_str.len,
200                         sock_info[bind_idx].address_str.s );
201         if (callid_suffix_len==-1 || callid_suffix_len>=CALLID_SUFFIX_LEN) {
202                 LOG(L_ERR, "ERROR: uac_child_init: buffer too small\n");
203                 return -1;
204         }
205         DBG("DEBUG: callid_suffix: %s\n", callid_suffix );
206         return 1;
207 }
208
209 static struct socket_info *uri2sock( str *uri, union sockaddr_union *to_su,
210                                                                          int proto )
211 {
212         struct proxy_l *proxy;
213         struct socket_info* send_sock;
214
215         proxy = uri2proxy(uri, proto);
216         if (proxy == 0) {
217                 ser_error = E_BAD_ADDRESS;
218                 LOG(L_ERR, "ERROR: uri2sock: Can't create a dst proxy\n");
219                 return 0;
220         }
221
222         hostent2su(to_su, &proxy->host, proxy->addr_idx, 
223                         (proxy->port) ? proxy->port : SIP_PORT);
224         send_sock=get_send_socket(to_su, proxy->proto);
225         if (send_sock == 0) {
226                 LOG(L_ERR, "ERROR: uri2sock: no corresponding socket for af %d,"
227                                 "proto %d\n", to_su->s.sa_family , proto);
228                 ser_error = E_NO_SOCKET;
229         }
230
231
232         free_proxy(proxy);
233         pkg_free(proxy);
234         return send_sock;
235 }
236         
237
238
239 /*
240  * Send a request within a dialog
241  * 
242  * Some parameters are required, some are optional (i.e., ephemeral,
243  * default or empty values are created if 0 is passed as parameter). The
244  * optional parameters are typically used to set some header fields
245  * to dialog-related values (as opposed to having them set to
246  * ephemeral values).
247  *
248  * Required:
249  * - msg ..   specifies type of message, such as "OPTIONS"
250  * - ruri ..  specifies request URI; 
251  * - from ..  value of From header field (if it already includes from tag, 
252  *            the fromtag parameter MUST point to en empty string; if 
253  *            fromtag is 0, an ephemeral tag is always appended)
254  * - to ...   value of To header field (if it already includes to tag in it,
255  *            or you do not wish to set a to-tag the totag parameter MUST be 0)
256  * 
257  * Optional:
258  * - dst     transport destination (expressed as URI) -- if present,
259  *           request is physically forwarded to address indicated in it,
260  *           overriding the transport address in ruri; useful for use with 
261  *           outbound proxies or loose routers (that is where the first 
262  *           element of route set comes in)
263  * - fromtag from HF tag -- dialog-less applications do not to set it (==0),
264  *           in which case an ephemeral value is created; if fromtag present,
265  *           its appended to the From header field; it may be also present 
266  *           and point to an empty string -- that only makes sense if
267  *           application includes the tag in From and does not care to
268  *           separate the tag from the rest of header field
269  * - totag   To HF tag; if 0, no to-tag is appended (unless it is already
270  *           part of to)
271  * - cid ..  callid; if 0, ephemeral value is created; transactions
272  *           within a dialog need to set this value to dialog's callid
273  * - cseq .. CSeq; if 0, default value (DEFAULT_CSEQ) is used; transactions
274  *           within a dialog need to set this value to current local cseq,
275  *           which grows continously with transactions sent
276  * - headers .. block of header fields that will be included in the
277  *           message. It MAY NOT include header fields already described
278  *           in other parameters (From, to, cid, cseq) or created 
279  *           automatically   (Content_length)   otherwise the parameter
280  *           would appear multiple times. It MUST include all additional
281  *           header fields required for a given SIP message, like Content-Type 
282  *           for any messages including a body or Contact for INVITEs.
283  * - body .. if present, body and Content-Length is appended to the 
284  *           SIP message; Content-Type then needs to be present inside
285  *           'headers' parameter
286  * - cb ..   callback to be called when transaction completes; if none
287  *           present, no callback will be called
288  * - cbp ..  callback parameter -- value stored in transaction context
289  *           
290  *
291  */
292 int t_uac_dlg(str* msg,                     /* Type of the message - MESSAGE, OPTIONS etc. */
293               str* dst,                     /* Real destination (can be different than R-URI) */
294                   int proto,
295               str* ruri,                    /* Request-URI */
296               str* to,                      /* To - w/o tag*/
297               str* from,                    /* From - w/o tag*/
298               str* totag,                   /* To tag */
299               str* fromtag,                 /* From tag */
300               int* cseq,                    /* Variable holding CSeq */
301               str* cid,                     /* Call-ID */
302               str* headers,                 /* Optional headers including CRLF */
303               str* body,                    /* Message body */
304               transaction_cb completion_cb, /* Callback parameter */
305               void* cbp                     /* Callback pointer */
306               )
307 {
308
309         int r, branch, ret;
310         unsigned int req_len;
311         char *buf;
312         struct cell *new_cell;
313         struct socket_info* send_sock;
314         struct retr_buf *request;
315         str callid_s, ftag, tmp;
316         union sockaddr_union to_su;
317
318         /* make -Wall shut up */
319         ret=0;
320
321         /* check for invalid parameter */
322         if (!msg || !msg->s
323                                 || !ruri || !ruri->s
324                                 || !from || !from->s
325                                 || !to || !to->s ) {
326                 LOG(L_ERR, "ERROR: t_uac_dlg: invalid parameters\n");
327                 ser_error = ret = E_INVALID_PARAMS;
328 #ifdef XL_DEBUG
329                 abort();
330 #endif
331                 goto done;
332         }
333
334         send_sock=uri2sock( dst? dst: ruri, &to_su, proto );
335         if (send_sock==0) {
336                 LOG(L_ERR, "ERROR: t_uac_dlg: no socket found\n");
337                 goto error00;
338         }
339
340         branch=0;
341              /* No Call-ID given, calculate it */
342         if (cid == 0) {
343                 callid_nr++;
344                 r = snprintf(callid, rand_len + 1, "%0*lx", rand_len, callid_nr);
345                 if (r == -1 || r>=rand_len+1) {
346                         LOG(L_CRIT, "BUG: SORRY, callid calculation failed\n");
347                         goto error00;
348                 }
349
350                      /* fix the ZT 0 */
351                 callid[rand_len] = CID_SEP;
352                 callid_s.s = callid;
353                 callid_s.len = rand_len + callid_suffix_len;
354         }
355
356         new_cell = build_cell(0); 
357         if (!new_cell) {
358                 ret = E_OUT_OF_MEM;
359                 LOG(L_ERR, "ERROR: t_uac: short of cell shmem\n");
360                 goto error00;
361         }
362
363         new_cell->completion_cb = completion_cb;
364         new_cell->cbp = cbp;
365
366         /* cbp is installed -- tell error handling bellow not to free it */
367         cbp = 0;
368
369         new_cell->is_invite = msg->len == INVITE_LEN && memcmp(msg->s, INVITE, INVITE_LEN) == 0;
370         new_cell->local= 1 ;
371         set_kr(REQ_FWDED);
372
373         request = &new_cell->uac[branch].request;
374         request->dst.to = to_su;
375         request->dst.send_sock = send_sock;
376         request->dst.proto = send_sock->proto;
377         request->dst.proto_reserved1 = 0;
378
379         /* need to put in table to calculate label which is needed for printing */
380         LOCK_HASH(new_cell->hash_index);
381         insert_into_hash_table_unsafe(new_cell);
382         UNLOCK_HASH(new_cell->hash_index);
383
384         if (fromtag == 0) {
385                      /* calculate from tag from callid */
386                 crcitt_string_array(&from_tag[MD5_LEN + 1], (cid) ? (cid) : (&callid_s), 1);
387                 ftag.s = from_tag; 
388                 ftag.len = FROM_TAG_LEN;
389         }
390
391         buf = build_uac_request_dlg(msg, 
392                                     ruri,
393                                     to, 
394                                     from,
395                                     totag,
396                                     (fromtag) ? (fromtag) : (&ftag), 
397                                     (cseq) ? (*cseq) : DEFAULT_CSEQ, 
398                                     (cid) ? (cid) : (&callid_s), 
399                                     headers, 
400                                     body, 
401                                     branch,
402                                     new_cell,
403                                     &req_len,
404                                         send_sock);
405         if (!buf) {
406                 ret = E_OUT_OF_MEM;
407                 LOG(L_ERR, "ERROR: t_uac: short of req shmem\n");
408                 goto error01;
409         }
410         new_cell->method.s = buf;
411         new_cell->method.len = msg->len;
412
413         request->buffer = buf;
414         request->buffer_len = req_len;
415         new_cell->nr_of_outgoings++;
416
417 /*
418         proxy->tx++;
419         proxy->tx_bytes += req_len;
420 */
421
422         if (SEND_BUFFER(request) == -1) {
423                 if (dst) {
424                         tmp = *dst;
425                 } else {
426                         tmp = *ruri;
427                 }
428                 LOG(L_ERR, "ERROR: t_uac: UAC sending to \'%.*s\' failed\n", tmp.len, tmp.s);
429 /*
430                 proxy->errors++;
431                 proxy->ok = 0;
432 */
433         }
434         
435         start_retr(request);
436
437         /* success */
438         return 1;
439
440 error01:
441         LOCK_HASH(new_cell->hash_index);
442         remove_from_hash_table_unsafe(new_cell);
443         UNLOCK_HASH(new_cell->hash_index);
444         free_cell(new_cell);
445
446 error00:
447 /*
448         free_proxy(proxy);
449         pkg_free(proxy);
450 */
451
452 done: 
453         /* if we did not install cbp, release it now */
454         if (cbp) shm_free(cbp);
455         return ser_error = ret;
456 }
457
458
459 static void fifo_callback( struct cell *t, struct sip_msg *reply,
460         int code, void *param)
461 {
462
463         char *filename;
464         str text;
465
466         DBG("DEBUG: fifo UAC completed with status %d\n", code);
467         if (!t->cbp) {
468                 LOG(L_INFO, "INFO: fifo UAC completed with status %d\n", code);
469                 return;
470         }
471
472         filename=(char *)(t->cbp);
473         if (reply==FAKED_REPLY) {
474                 get_reply_status(&text,reply,code);
475                 if (text.s==0) {
476                         LOG(L_ERR, "ERROR: fifo_callback: get_reply_status failed\n");
477                         fifo_reply(filename, "500 fifo_callback: get_reply_status failed\n");
478                         return;
479                 }
480                 fifo_reply(filename, "%.*s\n", text.len, text.s );
481                 pkg_free(text.s);
482         } else {
483                 text.s=reply->first_line.u.reply.status.s;
484                 text.len=reply->len-(reply->first_line.u.reply.status.s-reply->buf);
485                 fifo_reply(filename, "%.*s", text.len, text.s );
486         }
487         DBG("DEBUG: fifo_callback sucesssfuly completed\n");
488 }       
489
490 static struct str_list *new_str(char *s, int len, struct str_list **last, int *total)
491 {
492         struct str_list *new;
493         new=pkg_malloc(sizeof(struct str_list));
494         if (!new) {
495                 LOG(L_ERR, "ERROR: get_hfblock: not enough mem\n");
496                 return 0;
497         }
498         new->s.s=s;
499         new->s.len=len;
500         new->next=0;
501
502         (*last)->next=new;
503         *last=new;
504         *total+=len;
505
506         return new;
507 }
508
509
510 static char *get_hfblock(str *uri, struct hdr_field *hf, int *l, int proto) 
511 {
512         struct str_list sl, *last, *new, *i, *foo;
513         int hf_avail, frag_len, total_len;
514         char *begin, *needle, *dst, *ret, *d;
515         str *sock_name, *portname;
516         union sockaddr_union to_su;
517         struct socket_info* send_sock;
518
519         ret=0; /* pesimist: assume failure */
520         total_len=0;
521         last=&sl;
522         last->next=0;
523         portname=sock_name=0;
524
525         for (; hf; hf=hf->next) {
526                 if (skip_hf(hf)) continue;
527
528                 begin=needle=hf->name.s; 
529                 hf_avail=hf->len;
530
531                 /* substitution loop */
532                 while(hf_avail) {
533                         d=memchr(needle, SUBST_CHAR, hf_avail);
534                         if (!d || d+1>=needle+hf_avail) { /* nothing to substitute */
535                                 new=new_str(begin, hf_avail, &last, &total_len); 
536                                 if (!new) goto error;
537                                 break;
538                         } else {
539                                 frag_len=d-begin;
540                                 d++; /* d not at the second substitution char */
541                                 switch(*d) {
542                                         case SUBST_CHAR:        /* double SUBST_CHAR: IP */
543                                                 /* string before substitute */
544                                                 new=new_str(begin, frag_len, &last, &total_len); 
545                                                 if (!new) goto error;
546                                                 /* substitute */
547                                                 if (!sock_name) {
548                                                         send_sock=uri2sock( uri, &to_su, proto );
549                                                         if (!send_sock) {
550                                                                 LOG(L_ERR, "ERROR: get_hf_block: send_sock failed\n");
551                                                                 goto error;
552                                                         }
553                                                         sock_name=&send_sock->address_str;
554                                                         portname=&send_sock->port_no_str;
555                                                 }
556                                                 new=new_str(sock_name->s, sock_name->len,
557                                                                 &last, &total_len );
558                                                 if (!new) goto error;
559                                                 /* inefficient - FIXME --andrei*/
560                                                 new=new_str(":", 1, &last, &total_len);
561                                                 if (!new) goto error;
562                                                 new=new_str(portname->s, portname->len,
563                                                                 &last, &total_len );
564                                                 if (!new) goto error;
565                                                 /* keep going ... */
566                                                 begin=needle=d+1;hf_avail-=frag_len+2;
567                                                 continue;
568                                         default:
569                                                 /* no valid substitution char -- keep going */
570                                                 hf_avail-=frag_len+1;
571                                                 needle=d;
572                                 }
573                         } /* possible substitute */
574                 } /* substitution loop */
575                 /* proceed to next header */
576                 /* new=new_str(CRLF, CRLF_LEN, &last, &total_len );
577                 if (!new) goto error; */
578                 DBG("DEBUG: get_hf_block: one more hf processed\n");
579         } /* header loop */
580
581
582         /* construct a single header block now */
583         ret=pkg_malloc(total_len);
584         if (!ret) {
585                 LOG(L_ERR, "ERROR: get_hf_block no pkg mem for hf block\n");
586                 goto error;
587         }
588         i=sl.next;
589         dst=ret;
590         while(i) {
591                 foo=i;
592                 i=i->next;
593                 memcpy(dst, foo->s.s, foo->s.len);
594                 dst+=foo->s.len;
595                 pkg_free(foo);
596         }
597         *l=total_len;
598         return ret;
599
600 error:
601         i=sl.next;
602         while(i) {
603                 foo=i;
604                 i=i->next;
605                 pkg_free(foo);
606         }
607         *l=0;
608         return 0;
609 }
610
611 static void fifo_uac_error(char *reply_fifo, int code, char *msg)
612 {
613         LOG(L_ERR, "ERROR: fifo_uac: %s\n", msg ); 
614         fifo_reply(reply_fifo, "%d fifo_uac: %s", code, msg);
615 }
616
617 /* syntax:
618
619         :t_uac_dlg:[file] EOL
620         method EOL
621         r-uri EOL 
622         dst EOL                                 // ("." if no outbound server used)
623                                                         // must be used with dialogs/lr
624         <EOL separated HFs>+    // From and To must be present at least;
625                                                         // dialog-apps must include tag in From
626                                                         // (an ephemeral is appended otherwise)
627                                                         // and supply CSeq/CallId
628         .[EOL]
629         [body] 
630         .EOL
631
632
633         there is also the possibility to have server placed its
634     hostname:portnumber in header fields -- just put double
635         exclamation mark in any of the optional header fields
636         (i.e., any but From/To/CallID,CSeq), they will be 
637         substituted hn:pn
638
639 Example:
640
641 sc fifo t_uac_dlg MESSAGE sip:joe@192.168.2.1 \
642         . \ # no outbound proxy
643         'From:sender@iptel.org;tagd=123'  \ # no to-tag -> ephemeral
644         'To:sender@iptel.org' \
645         'Foo: sip:user@!! '  \ # expansion here
646         'CSEQ: 11 MESSAGE   ' \
647         . \ # EoH
648         .       # empty body
649 ---
650 U 192.168.2.16:5060 -> 192.168.2.1:5060
651 MESSAGE sip:joe@192.168.2.1 SIP/2.0..
652 Via: SIP/2.0/UDP 192.168.2.16;branch=z9hG4bK760c.922ea6a1.0..
653 To: sender@iptel.org..
654 From: sender@iptel.org;tagd=123;tag=5405e669bc2980663aed2624dc31396f-fa77..
655 CSeq: 11 MESSAGE..
656 Call-ID: e863bf56-22255@192.168.2.16..
657 Content-Length: 0..
658 User-Agent: Sip EXpress router (0.8.11pre4-tcp1-locking (i386/linux))..
659 Foo: sip:user@192.168.2.16:5060..
660 ..
661
662
663 */
664
665 int fifo_uac_dlg( FILE *stream, char *response_file ) 
666 {
667         char method_buf[MAX_METHOD];
668         char ruri_buf[MAX_URI_SIZE];
669         char outbound_buf[MAX_URI_SIZE];
670         char header_buf[MAX_HEADER]; 
671         char body_buf[MAX_BODY]; 
672         str method, ruri, outbound, header, body;
673         str hfb; /* header field block */
674         struct sip_uri parsed_ruri, parsed_outbound;
675         str dummy_empty;
676         int fromtag;
677         int cseq;
678         struct cseq_body *parsed_cseq;
679         int i;
680         char c;
681         struct to_body *parsed_from;
682
683
684         char *shmem_file;
685         int fn_len;
686         int ret;
687         int sip_error;
688         char err_buf[MAX_REASON_LEN];
689         int err_ret;
690         struct sip_msg faked_msg;
691
692
693         if (!read_line(method_buf, MAX_METHOD, stream,&method.len)
694                                         ||method.len==0) {
695                 /* line breaking must have failed -- consume the rest
696                    and proceed to a new request
697                 */
698                 fifo_uac_error(response_file, 400, "method expected");
699                 return 1;
700         }
701         method.s=method_buf;
702         DBG("DEBUG: fifo_uac: method: %.*s\n", method.len, method.s );
703
704         if (!read_line(ruri_buf, MAX_URI_SIZE, stream, &ruri.len)
705                                         || ruri.len==0) {
706                 fifo_uac_error(response_file, 400, "ruri expected");
707                 return 1;
708         }
709         if (parse_uri(ruri_buf, ruri.len, &parsed_ruri) < 0 ) {
710                 fifo_uac_error(response_file, 400, "ruri invalid\n");
711                 return 1;
712         }
713         ruri.s=ruri_buf;
714         DBG("DEBUG: fifo_uac:  ruri: %.*s\n", ruri.len, ruri.s);
715
716         if (!read_line(outbound_buf, MAX_URI_SIZE, stream, &outbound.len)
717                                         ||outbound.len==0) {
718                 fifo_uac_error(response_file, 400, "outbound address expected\n");
719                 return 1;
720         }
721         if (outbound.len==1 && outbound_buf[0]=='.' ) {
722                 DBG("DEBUG: fifo_uac: outbound empty\n");
723                 outbound.s=0; outbound.len=0;
724         } else if (parse_uri(outbound_buf, outbound.len, 
725                                                         &parsed_outbound) < 0 ) {
726                 fifo_uac_error(response_file, 400, "outbound uri invalid\n");
727                 return 1;
728         } else {
729                 outbound.s=outbound_buf;
730                 DBG("DEBUG: fifo_uac:  dst: %.*s\n", outbound.len, outbound.s);
731         }
732
733
734         /* now read and parse header fields */
735         if (!read_line_set(header_buf, MAX_HEADER, stream, &header.len)
736                                         || header.len==0 ) {
737                 fifo_uac_error(response_file, 400, "HFs expected");
738                 return 1;
739         }
740         header.s=header_buf;
741         DBG("DEBUG: fifo_uac: header: %.*s\n", header.len, header.s );
742         /* use SIP parser to look at what is in the FIFO request */
743         memset(&faked_msg, 0, sizeof(struct sip_msg));
744         faked_msg.len=header.len; 
745         faked_msg.buf=faked_msg.unparsed=header_buf;
746         if (parse_headers(&faked_msg, HDR_EOH, 0)==-1 ) {
747                         DBG("DEBUG: fifo_uac: parse_headers failed\n");
748                         fifo_uac_error(response_file, 400, "HFs unparseable");
749                         goto error;
750         }
751         DBG("DEBUG: fifo_uac: parse_headers succeeded\n");
752
753         /* and eventually body */
754         if (!read_body(body_buf, MAX_BODY, stream, &body.len)) {
755                 fifo_uac_error(response_file, 400, "body expected");
756                 goto error;
757         }
758         body.s=body_buf;
759         DBG("DEBUG: fifo_uac: body: %.*s\n", body.len, body.s );
760
761
762         /* at this moment, we collected all the things we got, let's
763          * verify user has not forgotten something */
764         if (body.len && !faked_msg.content_type) {
765                 fifo_uac_error(response_file, 400, "Content_type missing");
766                 goto error;
767         }
768         if (body.len && faked_msg.content_length) {
769                 fifo_uac_error(response_file, 400, "Content_length disallowed");
770                 goto error;
771         }
772         if (!faked_msg.to) {
773                 fifo_uac_error(response_file, 400, "To missing");
774                 goto error;
775         }
776         if (!faked_msg.from) {
777                 fifo_uac_error(response_file, 400, "From missing");
778                 goto error;
779         }
780         /* we also need to know if there is from-tag and add it otherwise */
781         if (parse_from_header(&faked_msg)<0) {
782                 fifo_uac_error(response_file, 400, "Error in From");
783                 goto error;
784         }
785         parsed_from=(struct to_body*)faked_msg.from->parsed;
786         fromtag=parsed_from->tag_value.s &&
787                         parsed_from->tag_value.len;
788         cseq=0;
789         if (faked_msg.cseq && (parsed_cseq=get_cseq(&faked_msg))) {
790                 for (i=0; i<parsed_cseq->number.len; i++ ) {
791                         c=parsed_cseq->number.s[i];
792                         if (c>='0' && c<'9' ) cseq=cseq*10+c-'0';
793                         else {
794                                 fifo_uac_error(response_file, 400, "non-nummerical CSeq");
795                                 goto error;
796                         }
797                 }
798                 if (parsed_cseq->method.len!=method.len 
799                                 || memcmp(parsed_cseq->method.s, method.s, method.len)!=0) {
800                         fifo_uac_error(response_file, 400, "CSeq method mismatch");
801                         goto error;
802                 }
803         }
804
805         hfb.s=get_hfblock(outbound.len ? &outbound : &ruri, 
806                                         faked_msg.headers, &hfb.len, PROTO_UDP);
807         if (!hfb.s) {
808                 fifo_uac_error(response_file, 500, "no mem for hf block");
809                 goto error;
810         }
811
812
813         DBG("DEBUG: fifo_uac: EoL -- proceeding to transaction creation\n");
814         /* we got it all, initiate transaction now! */
815         if (response_file) {
816                 fn_len=strlen(response_file)+1;
817                 shmem_file=shm_malloc(fn_len);
818                 if (shmem_file==0) {
819                         fifo_uac_error(response_file, 500, "no shmem");
820                         goto error01;
821                 }
822                 memcpy(shmem_file, response_file, fn_len );
823         } else {
824                 shmem_file=0;
825         }
826         /* HACK: there is yet a shortcoming -- if t_uac fails, callback
827            will not be triggered and no feedback will be printed
828            to shmem_file
829         */
830         dummy_empty.s=0; dummy_empty.len=0;
831         ret=t_uac_dlg( &method, 
832                 outbound.len ? &outbound: 0,
833                 PROTO_UDP,
834                 &ruri, 
835                 &faked_msg.to->body,    /* possibly w/to-tag in it */
836                 &faked_msg.from->body,
837                 &dummy_empty,                   /* if present, to-tag passed in to */
838                 fromtag ?                               /* if fromtag present, ... */
839                         &dummy_empty:           /* ... pass it in from ... */
840                         0,                                      /* use ephemeral otherwise */
841                 cseq ? &cseq : 0,
842                 faked_msg.callid ?
843                         &faked_msg.callid->body:
844                         0,
845                 &hfb,                                           /* headers -- TBD */
846                 &body,
847                 fifo_callback, shmem_file );
848
849
850         if (ret<=0) {
851                 err_ret=err2reason_phrase(ret, &sip_error, err_buf,
852                                 sizeof(err_buf), "FIFO/UAC" ) ;
853                 if (err_ret > 0 )
854                 {
855
856                         fifo_uac_error(response_file, sip_error, err_buf);
857                 } else {
858                         fifo_uac_error(response_file, 500, "FIFO/UAC error" );
859                 }
860         }
861
862 error01:
863         pkg_free(hfb.s);
864
865 error:
866         /* free_sip_msg(&faked_msg); */
867         if (faked_msg.headers) free_hdr_field_lst(faked_msg.headers);
868         return 1;
869 }