preliminary support for FIFO/t_uac added -- compiles, but not completed yet
[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
46
47 #include "defs.h"
48
49
50 #include <stdlib.h>
51 #include <sys/types.h>
52 #include <unistd.h>
53 #include <stdio.h>
54 #include <errno.h>
55 #include <sys/types.h>
56 #include <sys/stat.h>
57 #include <fcntl.h>
58 #include <signal.h>
59 #include <limits.h>
60 #include <string.h>
61 #include "../../dprint.h"
62 #include "../../ut.h"
63 #include "../../hash_func.h"
64 #include "../../md5utils.h"
65 #include "../../mem/mem.h"
66 #include "../../fifo_server.h"
67 #include "../../error.h"
68 #include "../../pt.h"
69 #include "../../crc.h"
70 #include "t_funcs.h"
71 #include "config.h"
72 #include "sip_msg.h"
73 #include "ut.h"
74 #include "t_msgbuilder.h"
75 #include "uac.h"
76
77 /* Call-ID has the following form: <callid_nr>-<pid>@<ip>
78  * callid_nr is initialized as a random number and continually
79  * increases; -<pid>@<ip> is kept in callid_suffix
80  */
81
82 #define CALLID_SUFFIX_LEN (1 /* - */ + 5 /* pid */ \
83         + 42 /* embedded v4inv6 address can be looong '128.' */ \
84         + 2 /* parenthessis [] */ + 1 /* ZT 0 */ \
85         + 16 /* one never knows ;-) */ )
86 #define CALLID_NR_LEN 20
87
88 /* the character which separates random from constant part */
89 #define CID_SEP '-'
90
91 /* length of FROM tags */
92 #define FROM_TAG_LEN (MD5_LEN +1 /* - */ + CRC16_LEN)
93
94 static unsigned long callid_nr;
95 static char *callid_suffix;
96 static int callid_suffix_len;
97 static int rand_len;    /* number of chars to display max rand */
98 static char callid[CALLID_NR_LEN+CALLID_SUFFIX_LEN];
99
100 #ifndef DEPRECATE_OLD_STUFF
101 char *uac_from="\"UAC Account\" <sip:uac@dev.null:9>";
102 str uac_from_str;
103 #endif
104
105 static char from_tag[ FROM_TAG_LEN+1 ];
106
107
108
109 int uac_init() {
110
111         int i; 
112         unsigned long uli;
113         int rand_len_bits;
114         int rand_cnt; /* number of rands() to be long enough */
115         int rand_bits; /* length of rands() in bits */
116         str src[3];
117
118         if (RAND_MAX<TABLE_ENTRIES) {
119                 LOG(L_WARN, "Warning: uac does not spread "
120                         "accross the whole hash table\n");
121         }
122
123         /* calculate the initial call-id */
124
125         /* how many bits and chars do we need to display the 
126          * whole ULONG number */
127         for (rand_len_bits=0,uli=ULONG_MAX;uli;
128                         uli>>=1, rand_len_bits++ );
129         rand_len=rand_len_bits/4;
130         if (rand_len>CALLID_NR_LEN) {
131                 LOG(L_ERR, "ERROR: Too small callid buffer\n");
132                 return -1;
133         }
134
135         /* how long are the rand()s ? */
136         for (rand_bits=0,i=RAND_MAX;i;i>>=1,rand_bits++);
137         /* how many rands() fit in the ULONG ? */
138         rand_cnt=rand_len_bits / rand_bits;
139
140         /* now fill in the callid with as many random
141          * numbers as you can + 1 */
142         callid_nr=rand(); /* this is the + 1 */
143         while(rand_cnt) {
144                 rand_cnt--;
145                 callid_nr<<=rand_bits;
146                 callid_nr|=rand();
147         }
148         callid_suffix=callid+rand_len;
149         DBG("CALLID initialization: %lx (len=%d)\n", 
150                         callid_nr, rand_len );
151         DBG("CALLID0=%0*lx\n", rand_len, callid_nr );
152
153
154         /* calculate the initial From tag */
155
156         src[0].s="Long live SER server";
157         src[0].len=strlen(src[0].s);
158         src[1].s=sock_info[bind_idx].address_str.s;
159         src[1].len=strlen(src[1].s);
160         src[2].s=sock_info[bind_idx].port_no_str.s;
161         src[2].len=strlen(src[2].s);
162
163         MDStringArray( from_tag, src, 3 );
164         from_tag[MD5_LEN]=CID_SEP;
165
166 #ifndef DEPRECATE_OLD_STUFF
167         uac_from_str.s = uac_from;
168         uac_from_str.len = strlen(uac_from);
169 #endif
170
171         return 1;
172 }
173
174
175 int uac_child_init( int rank ) 
176 {
177         callid_suffix_len=snprintf(callid_suffix,CALLID_SUFFIX_LEN,
178                         "%c%d@%.*s", CID_SEP, my_pid(), 
179                         sock_info[bind_idx].address_str.len,
180                         sock_info[bind_idx].address_str.s );
181         if (callid_suffix_len==-1 || callid_suffix_len>=CALLID_SUFFIX_LEN) {
182                 LOG(L_ERR, "ERROR: uac_child_init: buffer too small\n");
183                 return -1;
184         }
185         DBG("DEBUG: callid_suffix: %s\n", callid_suffix );
186         return 1;
187 }
188
189 #ifndef DEPRECATE_OLD_STUFF
190 int t_uac( str *msg_type, str *dst, 
191         str *headers, str *body, str *from, 
192         transaction_cb completion_cb, void *cbp, 
193         dlg_t dlg)
194 {
195
196         int r;
197         struct cell *new_cell;
198         struct proxy_l *proxy;
199         int branch;
200         int ret;
201         unsigned int req_len;
202         char *buf;
203         union sockaddr_union to;
204         struct socket_info* send_sock;
205         struct retr_buf *request;
206         str dummy_from;
207         str callid_s;
208         str fromtag;
209
210         /* make -Wall shut up */
211         ret=0;
212
213         proxy=uri2proxy( dst );
214         if (proxy==0) {
215                 ser_error=ret=E_BAD_ADDRESS;
216                 LOG(L_ERR, "ERROR: t_uac: can't create a dst proxy\n");
217                 goto done;
218         }
219         branch=0;
220         /* might go away -- we ignore it in send_pr_buffer anyway */
221         /* T->uac[branch].request.to_len=sizeof(union sockaddr_union); */
222         hostent2su(&to, &proxy->host, proxy->addr_idx, 
223                 (proxy->port)?htons(proxy->port):htons(SIP_PORT));
224         send_sock=get_send_socket( &to, PROTO_UDP );
225         if (send_sock==0) {
226                 LOG(L_ERR, "ERROR: t_uac: no corresponding listening socket "
227                         "for af %d\n", to.s.sa_family );
228                 ret=E_NO_SOCKET;
229                 goto error00;
230         }
231
232         /* update callid */
233         /* generate_callid(); */
234         callid_nr++;
235         r=snprintf(callid, rand_len+1, "%0*lx", rand_len, callid_nr );
236         if (r==-1 || r>=rand_len+1) {
237                 LOG(L_CRIT, "BUG: SORRY, callid calculation failed\n");
238                 goto error00;
239         }
240         /* fix the ZT 0 */
241         callid[rand_len]=CID_SEP;
242         callid_s.s=callid;
243         callid_s.len=rand_len+callid_suffix_len;
244         DBG("DEBUG: sufix_len = %d\n",callid_suffix_len);
245         DBG("DEBUG: NEW CALLID:%.*s[%d]:\n", callid_s.len, callid_s.s 
246                 , callid_s.len);
247         new_cell = build_cell( NULL ) ; 
248         if (!new_cell) {
249                 ret=E_OUT_OF_MEM;
250                 LOG(L_ERR, "ERROR: t_uac: short of cell shmem\n");
251                 goto error00;
252         }
253         new_cell->completion_cb=completion_cb;
254         new_cell->cbp=cbp;
255         /* cbp is installed -- tell error handling bellow not to free it */
256         cbp=0;
257         new_cell->is_invite=msg_type->len==INVITE_LEN 
258                 && memcmp(msg_type->s, INVITE, INVITE_LEN)==0;
259         new_cell->local=1;
260         new_cell->kr=REQ_FWDED;
261
262
263         request=&new_cell->uac[branch].request;
264         request->to=to;
265         request->send_sock=send_sock;
266
267         /* need to put in table to calculate label which is needed for printing */
268         LOCK_HASH(new_cell->hash_index);
269         insert_into_hash_table_unsafe(  new_cell );
270         UNLOCK_HASH(new_cell->hash_index);
271
272         if (from) dummy_from=*from; else { dummy_from.s=0; dummy_from.len=0; }
273         /* calculate from tag from callid */
274         crcitt_string_array(&from_tag[MD5_LEN+1], &callid_s, 1 );
275         fromtag.s=from_tag; fromtag.len=FROM_TAG_LEN;
276         buf=build_uac_request(  *msg_type, *dst, 
277                         dummy_from, fromtag,
278                         DEFAULT_CSEQ, callid_s, 
279                         *headers, *body, branch,
280                         new_cell, /* t carries hash_index, label, md5,
281                                 uac[].send_sock and other pieces of
282                                 information needed to print a message*/
283                 &req_len );
284         if (!buf) {
285                 ret=E_OUT_OF_MEM;
286                 LOG(L_ERR, "ERROR: t_uac: short of req shmem\n");
287                 goto error01;
288         }      
289         new_cell->method.s=buf;new_cell->method.len=msg_type->len;
290
291
292         request->buffer = buf;
293         request->buffer_len = req_len;
294         new_cell->nr_of_outgoings++;
295
296
297         proxy->tx++;
298         proxy->tx_bytes+=req_len;
299
300         if (SEND_BUFFER( request)==-1) {
301                 LOG(L_ERR, "ERROR: t_uac: UAC sending to %.*s failed\n",
302                         dst->len, dst->s );
303                 proxy->errors++;
304                 proxy->ok=0;
305         }
306         start_retr( request );
307
308         /* success */
309         return 1;
310
311 error01:
312         LOCK_HASH(new_cell->hash_index);
313         remove_from_hash_table_unsafe( new_cell );
314         UNLOCK_HASH(new_cell->hash_index);
315         free_cell(new_cell);
316 error00:
317         free_proxy( proxy );
318         free( proxy );
319 done: 
320         /* if we did not install cbp, release it now */
321         if (cbp) shm_free(cbp);
322         return ser_error=ret;
323 }
324 #endif
325
326
327 /*
328  * Send a request within a dialog
329  * 
330  * Some parameters are required, some are optional (i.e., ephemeral
331  * or default values are created if 0 is passed as parameter). The
332  * optional parameters are typically used to set some header fields
333  * to dialog-related values (as opposed to having them set to
334  * ephemeral values).
335  *
336  * Required:
337  * - msg ..   specifies type of message, such as "OPTIONS"
338  * - ruri ..  specifies request URI; 
339  * - from ..  value of From header field (if it already includes from tag, 
340  *            the fromtag parameter MUST point to en empty string)
341  * - to ...   value of To header field (if it already includes to tag,
342  *            the totag parameter MUST point to an empty string)
343  * - totag .. to tag
344  * 
345  * Optional:
346  * - dst     transport destination (expressed as URI) -- if present,
347  *           request is physically forwarded to address indicated in it,
348  *           overriding the transport address in ruri; useful for use with 
349  *           outbound proxies or loose routers (that is where the first 
350  *           element of route set comes in)
351  * - fromtag from HF tag -- dialog-less applications do not to set it (==0),
352  *           in which case an ephemeral value is created; if fromtag present,
353  *           its appended to the From header field; it may be also present 
354  *           and point to an empty string -- that only makes sense if
355  *           application includes the tag in From and does not care to
356  *           separate the tag from the rest of header field
357  * - cid ..  callid; if 0, ephemeral value is created; transactions
358  *           within a dialog need to set this value to dialog's callid
359  * - cseq .. CSeq; if 0, default value (DEFAULT_CSEQ) is used; transactions
360  *           within a dialog need to set this value to current local cseq,
361  *           which grows continously with transactions sent
362  * - headers .. block of header fields that will be included in the
363  *           message. It MAY NOT include header fields already described
364  *           in other parameters (From, to, cid, cseq) or created 
365  *           automatically   (Content_length)   otherwise the parameter
366  *           would appear multiple times. It MUST include all additional
367  *           header fields required for a given SIP message, like Content-Type 
368  *           for any messages including a body or Contact for INVITEs.
369  * - body .. if present, body and Content-Length is appended to the 
370  *           SIP message; Content-Type then needs to be present inside
371  *           'headers' parameter
372  * - cb ..   callback to be called when transaction completes; if none
373  *           present, no callback will be called
374  * - cbp ..  callback parameter -- value passed to callback function
375  *           when called
376  *
377  */
378 int t_uac_dlg(str* msg,                     /* Type of the message - MESSAGE, OPTIONS etc. */
379               str* dst,                     /* Real destination (can be different than R-URI) */
380               str* ruri,                    /* Request-URI */
381               str* to,                      /* To - w/o tag*/
382               str* from,                    /* From - w/o tag*/
383               str* totag,                   /* To tag */
384               str* fromtag,                 /* From tag */
385               int* cseq,                    /* Variable holding CSeq */
386               str* cid,                     /* Call-ID */
387               str* headers,                 /* Optional headers including CRLF */
388               str* body,                    /* Message body */
389               transaction_cb completion_cb, /* Callback parameter */
390               void* cbp                     /* Callback pointer */
391               )
392 {
393
394         int r, branch, ret;
395         unsigned int req_len;
396         char *buf;
397         struct cell *new_cell;
398         struct proxy_l *proxy;
399         union sockaddr_union to_su;
400         struct socket_info* send_sock;
401         struct retr_buf *request;
402         str callid_s, ftag, tmp;
403
404         /* make -Wall shut up */
405         ret=0;
406
407         /* check for invalid parameter */
408         if (!msg || !msg->s
409                                 || !ruri || !ruri->s
410                                 || !from || !from->s
411                                 || !to || !to->s
412                                 || !totag || !totag->s ) {
413                 LOG(L_ERR, "ERROR: t_uac_dlg: invalud parameters\n");
414                 ser_error = ret = E_INVALID_PARAMS;
415                 goto done;
416         }
417
418         proxy = uri2proxy((dst) ? (dst) : ruri);
419         if (proxy == 0) {
420                 ser_error = ret = E_BAD_ADDRESS;
421                 LOG(L_ERR, "ERROR: t_uac_dlg: Can't create a dst proxy\n");
422                 goto done;
423         }
424
425         branch=0;
426         hostent2su(&to_su, &proxy->host, proxy->addr_idx, (proxy->port) ? htons(proxy->port) : htons(SIP_PORT));
427         send_sock=get_send_socket(&to_su, PROTO_UDP);
428         if (send_sock == 0) {
429                 LOG(L_ERR, "ERROR: t_uac_dlg: no corresponding listening socket for af %d\n", to_su.s.sa_family );
430                 ret = E_NO_SOCKET;
431                 goto error00;
432         }
433         
434              /* No Call-ID given, calculate it */
435         if (cid == 0) {
436                 callid_nr++;
437                 r = snprintf(callid, rand_len + 1, "%0*lx", rand_len, callid_nr);
438                 if (r == -1 || r>=rand_len+1) {
439                         LOG(L_CRIT, "BUG: SORRY, callid calculation failed\n");
440                         goto error00;
441                 }
442
443                      /* fix the ZT 0 */
444                 callid[rand_len] = CID_SEP;
445                 callid_s.s = callid;
446                 callid_s.len = rand_len + callid_suffix_len;
447         }
448
449         new_cell = build_cell(0); 
450         if (!new_cell) {
451                 ret = E_OUT_OF_MEM;
452                 LOG(L_ERR, "ERROR: t_uac: short of cell shmem\n");
453                 goto error00;
454         }
455
456         new_cell->completion_cb = completion_cb;
457         new_cell->cbp = cbp;
458
459         /* cbp is installed -- tell error handling bellow not to free it */
460         cbp = 0;
461
462         new_cell->is_invite = msg->len == INVITE_LEN && memcmp(msg->s, INVITE, INVITE_LEN) == 0;
463         new_cell->local= 1 ;
464         new_cell->kr = REQ_FWDED;
465
466         request = &new_cell->uac[branch].request;
467         request->to = to_su;
468         request->send_sock = send_sock;
469
470         /* need to put in table to calculate label which is needed for printing */
471         LOCK_HASH(new_cell->hash_index);
472         insert_into_hash_table_unsafe(new_cell);
473         UNLOCK_HASH(new_cell->hash_index);
474
475         if (fromtag == 0) {
476                      /* calculate from tag from callid */
477                 crcitt_string_array(&from_tag[MD5_LEN + 1], (cid) ? (cid) : (&callid_s), 1);
478                 ftag.s = from_tag; 
479                 ftag.len = FROM_TAG_LEN;
480         }
481
482         buf = build_uac_request_dlg(msg, 
483                                     ruri,
484                                     to, 
485                                     from,
486                                     totag,
487                                     (fromtag) ? (fromtag) : (&ftag), 
488                                     (cseq) ? (*cseq) : DEFAULT_CSEQ, 
489                                     (cid) ? (cid) : (&callid_s), 
490                                     headers, 
491                                     body, 
492                                     branch,
493                                     new_cell,
494                                     &req_len);
495         if (!buf) {
496                 ret = E_OUT_OF_MEM;
497                 LOG(L_ERR, "ERROR: t_uac: short of req shmem\n");
498                 goto error01;
499         }
500         new_cell->method.s = buf;
501         new_cell->method.len = msg->len;
502
503         request->buffer = buf;
504         request->buffer_len = req_len;
505         new_cell->nr_of_outgoings++;
506
507         proxy->tx++;
508         proxy->tx_bytes += req_len;
509
510         if (SEND_BUFFER(request) == -1) {
511                 if (dst) {
512                         tmp = *dst;
513                 } else {
514                         tmp = *ruri;
515                 }
516                 LOG(L_ERR, "ERROR: t_uac: UAC sending to \'%.*s\' failed\n", tmp.len, tmp.s);
517                 proxy->errors++;
518                 proxy->ok = 0;
519         }
520         
521         start_retr(request);
522
523         /* success */
524         return 1;
525
526 error01:
527         LOCK_HASH(new_cell->hash_index);
528         remove_from_hash_table_unsafe(new_cell);
529         UNLOCK_HASH(new_cell->hash_index);
530         free_cell(new_cell);
531
532 error00:
533         free_proxy(proxy);
534         free(proxy);
535
536 done: 
537         /* if we did not install cbp, release it now */
538         if (cbp) shm_free(cbp);
539         return ser_error = ret;
540 }
541
542
543 static void fifo_callback( struct cell *t, struct sip_msg *msg,
544         int code, void *param)
545 {
546
547         char *filename;
548         str text;
549
550         DBG("DEBUG: fifo UAC completed with status %d\n", code);
551         if (!t->cbp) {
552                 LOG(L_INFO, "INFO: fifo UAC completed with status %d\n", code);
553                 return;
554         }
555
556         filename=(char *)(t->cbp);
557         get_reply_status(&text,msg,code);
558         if (text.s==0) {
559                 LOG(L_ERR, "ERROR: fifo_callback: get_reply_status failed\n");
560                 fifo_reply(filename, "500 fifo_callback: get_reply_status failed\n");
561                 return;
562         }
563         fifo_reply(filename, "%.*s", text.len, text.s );
564         pkg_free(text.s);
565         DBG("DEBUG: fifo_callback sucesssfuly completed\n");
566 }       
567
568 /* to be obsoleted in favor of fifo_uac_from */
569 int fifo_uac( FILE *stream, char *response_file ) 
570 {
571         char method[MAX_METHOD];
572         char header[MAX_HEADER];
573         char body[MAX_BODY];
574         char dst[MAX_DST];
575         str sm, sh, sb, sd;
576         char *shmem_file;
577         int fn_len;
578         int ret;
579         int sip_error;
580         char err_buf[MAX_REASON_LEN];
581
582         sm.s=method; sh.s=header; sb.s=body; sd.s=dst;
583         if (!read_line(method, MAX_METHOD, stream,&sm.len)||sm.len==0) {
584                 /* line breaking must have failed -- consume the rest
585                    and proceed to a new request
586                 */
587                 LOG(L_ERR, "ERROR: fifo_uac: method expected\n");
588                 fifo_reply(response_file, 
589                         "400 fifo_uac: method expected");
590                 return 1;
591         }
592         DBG("DEBUG: fifo_uac: method: %.*s\n", sm.len, method );
593         if (!read_line(dst, MAX_DST, stream, &sd.len)||sd.len==0) {
594                 fifo_reply(response_file, 
595                         "400 fifo_uac: destination expected\n");
596                 LOG(L_ERR, "ERROR: fifo_uac: destination expected\n");
597                 return 1;
598         }
599         DBG("DEBUG: fifo_uac:  dst: %.*s\n", sd.len, dst );
600         /* now read header fields line by line */
601         if (!read_line_set(header, MAX_HEADER, stream, &sh.len)) {
602                 fifo_reply(response_file, 
603                         "400 fifo_uac: HFs expected\n");
604                 LOG(L_ERR, "ERROR: fifo_uac: header fields expected\n");
605                 return 1;
606         }
607         DBG("DEBUG: fifo_uac: header: %.*s\n", sh.len, header );
608         /* and eventually body */
609         if (!read_body(body, MAX_BODY, stream, &sb.len)) {
610                 fifo_reply(response_file, 
611                         "400 fifo_uac: body expected\n");
612                 LOG(L_ERR, "ERROR: fifo_uac: body expected\n");
613                 return 1;
614         }
615         DBG("DEBUG: fifo_uac: body: %.*s\n", sb.len, body );
616         DBG("DEBUG: fifo_uac: EoL -- proceeding to transaction creation\n");
617         /* we got it all, initiate transaction now! */
618         if (response_file) {
619                 fn_len=strlen(response_file)+1;
620                 shmem_file=shm_malloc(fn_len);
621                 if (shmem_file==0) {
622                         LOG(L_ERR, "ERROR: fifo_uac: no shmem\n");
623                         fifo_reply(response_file, 
624                                 "500 fifo_uac: no shmem for shmem_file\n");
625                         return 1;
626                 }
627                 memcpy(shmem_file, response_file, fn_len );
628         } else {
629                 shmem_file=0;
630         }
631         ret=t_uac(&sm,&sd,&sh,&sb, 0 /* default from */,
632                 fifo_callback,shmem_file,0 /* no dialog */);
633         if (ret>0) {
634                 if (err2reason_phrase(ret, &sip_error, err_buf,
635                                 sizeof(err_buf), "FIFO/UAC" ) > 0 ) 
636                 {
637                         fifo_reply(response_file, "500 FIFO/UAC error: %d\n",
638                                 ret );
639                 } else {
640                         fifo_reply(response_file, err_buf );
641                 }
642         }
643         return 1;
644 }
645
646 #ifndef DEPRECATE_OLD_STUFF
647
648 /* syntax:
649
650         :t_uac_from:[file] EOL
651         method EOL
652         [from] EOL (if none, server's default from is taken)
653         dst EOL (put in r-uri and To)
654         [CR-LF separated HFs]* EOL
655         EOL
656         [body] EOL
657         EOL
658
659 */
660
661 int fifo_uac_from( FILE *stream, char *response_file ) 
662 {
663         char method[MAX_METHOD];
664         char header[MAX_HEADER];
665         char body[MAX_BODY];
666         char dst[MAX_DST];
667         char from[MAX_FROM];
668         str sm, sh, sb, sd, sf;
669         char *shmem_file;
670         int fn_len;
671         int ret;
672         int sip_error;
673         char err_buf[MAX_REASON_LEN];
674         int err_ret;
675
676         sm.s=method; sh.s=header; sb.s=body; sd.s=dst;sf.s=from;
677
678         if (!read_line(method, MAX_METHOD, stream,&sm.len)||sm.len==0) {
679                 /* line breaking must have failed -- consume the rest
680                    and proceed to a new request
681                 */
682                 LOG(L_ERR, "ERROR: fifo_uac: method expected\n");
683                 fifo_reply(response_file, 
684                         "400 fifo_uac: method expected");
685                 return 1;
686         }
687         DBG("DEBUG: fifo_uac: method: %.*s\n", sm.len, method );
688         if (!read_line(from, MAX_FROM, stream, &sf.len)) {
689                 fifo_reply(response_file, 
690                         "400 fifo_uac: from expected\n");
691                 LOG(L_ERR, "ERROR: fifo_uac: from expected\n");
692                 return 1;
693         }
694         DBG("DEBUG: fifo_uac:  from: %.*s\n", sf.len, from);
695         if (!read_line(dst, MAX_DST, stream, &sd.len)||sd.len==0) {
696                 fifo_reply(response_file, 
697                         "400 fifo_uac: destination expected\n");
698                 LOG(L_ERR, "ERROR: fifo_uac: destination expected\n");
699                 return 1;
700         }
701         DBG("DEBUG: fifo_uac:  dst: %.*s\n", sd.len, dst );
702         /* now read header fields line by line */
703         if (!read_line_set(header, MAX_HEADER, stream, &sh.len)) {
704                 fifo_reply(response_file, 
705                         "400 fifo_uac: HFs expected\n");
706                 LOG(L_ERR, "ERROR: fifo_uac: header fields expected\n");
707                 return 1;
708         }
709         DBG("DEBUG: fifo_uac: header: %.*s\n", sh.len, header );
710         /* and eventually body */
711         if (!read_body(body, MAX_BODY, stream, &sb.len)) {
712                 fifo_reply(response_file, 
713                         "400 fifo_uac: body expected\n");
714                 LOG(L_ERR, "ERROR: fifo_uac: body expected\n");
715                 return 1;
716         }
717         DBG("DEBUG: fifo_uac: body: %.*s\n", sb.len, body );
718         DBG("DEBUG: fifo_uac: EoL -- proceeding to transaction creation\n");
719         /* we got it all, initiate transaction now! */
720         if (response_file) {
721                 fn_len=strlen(response_file)+1;
722                 shmem_file=shm_malloc(fn_len);
723                 if (shmem_file==0) {
724                         LOG(L_ERR, "ERROR: fifo_uac: no shmem\n");
725                         fifo_reply(response_file, 
726                                 "500 fifo_uac: no memory for shmem_file\n");
727                         return 1;
728                 }
729                 memcpy(shmem_file, response_file, fn_len );
730         } else {
731                 shmem_file=0;
732         }
733         /* HACK: there is yet a shortcoming -- if t_uac fails, callback
734            will not be triggered and no feedback will be printed
735            to shmem_file
736         */
737         ret=t_uac(&sm,&sd,&sh,&sb, sf.len==0 ? 0 : &sf /* default from */,
738                 fifo_callback,shmem_file,0 /* no dialog */);
739         if (ret<=0) {
740                 err_ret=err2reason_phrase(ret, &sip_error, err_buf,
741                                 sizeof(err_buf), "FIFO/UAC" ) ;
742                 if (err_ret > 0 )
743                 {
744                         fifo_reply(response_file, "%d %s", sip_error, err_buf );
745                 } else {
746                         fifo_reply(response_file, "500 FIFO/UAC error: %d\n",
747                                 ret );
748                 }
749         }
750         return 1;
751
752 }
753
754 #endif
755
756
757 static void fifo_uac_error(char *reply_fifo, int code, char *msg)
758 {
759         LOG(L_ERR, "ERROR: fifo_uac: %s\n", msg ); 
760         fifo_reply(reply_fifo, "%d fifo_uac: %s", code, msg);
761 }
762
763 /* syntax:
764
765         :t_uac_dlg:[file] EOL
766         method EOL
767         r-uri EOL 
768         dst EOL                                 // ("." if no outbound server used)
769                                                         // must be used with dialogs/lr
770         <EOL separated HFs>+    // From and To must be present at least;
771                                                         // dialog-apps must include tag in From
772                                                         // (an ephemeral is appended otherwise)
773                                                         // and supply CSeq/CallId
774         .[EOL]
775         [body] 
776         .EOL
777
778 */
779
780 int fifo_uac_dlg( FILE *stream, char *response_file ) 
781 {
782         char method_buf[MAX_METHOD];
783         char ruri_buf[MAX_URI_SIZE];
784         char outbound_buf[MAX_URI_SIZE];
785         char header_buf[MAX_HEADER]; 
786         char body_buf[MAX_BODY]; 
787         str method, ruri, outbound, header, body;
788         struct sip_uri parsed_ruri, parsed_outbound;
789         str dummy_empty;
790         int fromtag;
791         int cseq;
792         struct cseq_body *parsed_cseq;
793         int i;
794         char c;
795         struct to_body *parsed_from;
796
797
798         char *shmem_file;
799         int fn_len;
800         int ret;
801         int sip_error;
802         char err_buf[MAX_REASON_LEN];
803         int err_ret;
804         struct sip_msg faked_msg;
805
806
807         if (!read_line(method_buf, MAX_METHOD, stream,&method.len)
808                                         ||method.len==0) {
809                 /* line breaking must have failed -- consume the rest
810                    and proceed to a new request
811                 */
812                 fifo_uac_error(response_file, 400, "method expected");
813                 return 1;
814         }
815         method.s=method_buf;
816         DBG("DEBUG: fifo_uac: method: %.*s\n", method.len, method.s );
817
818         if (!read_line(ruri_buf, MAX_URI_SIZE, stream, &ruri.len)
819                                         || ruri.len==0) {
820                 fifo_uac_error(response_file, 400, "ruri expected");
821                 return 1;
822         }
823         if (!parse_uri(ruri_buf, ruri.len, &parsed_ruri) < 0 ) {
824                 fifo_uac_error(response_file, 400, "ruri invalid\n");
825                 return 1;
826         }
827         ruri.s=ruri_buf;
828         DBG("DEBUG: fifo_uac:  ruri: %.*s\n", ruri.len, ruri.s);
829
830         if (!read_line(outbound_buf, MAX_URI_SIZE, stream, &outbound.len)
831                                         ||outbound.len==0) {
832                 fifo_uac_error(response_file, 400, "outbound address expected");
833                 return 1;
834         }
835         if (outbound.len==1 && outbound_buf[0]=='.' ) {
836                 DBG("DEBUG: fifo_uac: outbound empty");
837                 outbound.s=0; outbound.len=0;
838         } else if (!parse_uri(outbound_buf, outbound.len, 
839                                                         &parsed_outbound) < 0 ) {
840                 fifo_uac_error(response_file, 400, "outbound uri invalid\n");
841                 return 1;
842         } else {
843                 outbound.s=outbound_buf;
844                 DBG("DEBUG: fifo_uac:  dst: %.*s\n", outbound.len, outbound.s);
845         }
846
847
848         /* now read and parse header fields */
849         if (!read_line_set(header_buf, MAX_HEADER, stream, &header.len)
850                                         || header.len==0 ) {
851                 fifo_uac_error(response_file, 400, "HFs expected");
852                 return 1;
853         }
854         header.s=header_buf;
855         DBG("DEBUG: fifo_uac: header: %.*s\n", header.len, header.s );
856         /* use SIP parser to look at what is in the FIFO request */
857         memset(&faked_msg, 0, sizeof(struct sip_msg));
858         faked_msg.len=header.len; faked_msg.unparsed=header_buf;
859         if (parse_headers(&faked_msg, HDR_EOH, 0)==-1 ) {
860                         fifo_uac_error(response_file, 400, "HFs unparseable");
861                         goto error;
862         }
863
864         /* and eventually body */
865         if (!read_body(body_buf, MAX_BODY, stream, &body.len)) {
866                 fifo_uac_error(response_file, 400, "body expected");
867                 goto error;
868         }
869         body.s=body_buf;
870         DBG("DEBUG: fifo_uac: body: %.*s\n", body.len, body.s );
871
872
873         /* at this moment, we collected all the things we got, let's
874          * verify user has not forgotten something */
875         if (body.len && !faked_msg.content_type) {
876                 fifo_uac_error(response_file, 400, "Content_type missing");
877                 goto error;
878         }
879         if (body.len && faked_msg.content_length) {
880                 fifo_uac_error(response_file, 400, "Content_length disallowed");
881                 goto error;
882         }
883         if (!faked_msg.to) {
884                 fifo_uac_error(response_file, 400, "To missing");
885                 goto error;
886         }
887         if (!faked_msg.from) {
888                 fifo_uac_error(response_file, 400, "From missing");
889                 goto error;
890         }
891         /* we also need to know if there is from-tag and add it otherwise */
892         if (parse_from_header(&faked_msg)<0) {
893                 fifo_uac_error(response_file, 400, "Error in From");
894                 goto error;
895         }
896         parsed_from=(struct to_body*)faked_msg.from->parsed;
897         fromtag=parsed_from->tag_value.s &&
898                         parsed_from->tag_value.len;
899         cseq=0;
900         if (faked_msg.cseq && (parsed_cseq=get_cseq(&faked_msg))) {
901                 for (i=0; i<parsed_cseq->number.len; i++ ) {
902                         c=parsed_cseq->number.s[i];
903                         if (c>='0' && c<'9' ) cseq=cseq*10+c-'0';
904                         else {
905                                 fifo_uac_error(response_file, 400, "non-nummerical CSeq");
906                                 goto error;
907                         }
908                 }
909                 if (parsed_cseq->method.len!=method.len 
910                                 || memcmp(parsed_cseq->method.s, method.s, method.len)!=0) {
911                         fifo_uac_error(response_file, 400, "CSeq method mismatch");
912                         goto error;
913                 }
914         }
915
916
917
918
919         DBG("DEBUG: fifo_uac: EoL -- proceeding to transaction creation\n");
920         /* we got it all, initiate transaction now! */
921         if (response_file) {
922                 fn_len=strlen(response_file)+1;
923                 shmem_file=shm_malloc(fn_len);
924                 if (shmem_file==0) {
925                         fifo_uac_error(response_file, 500, "no shmem");
926                         goto error;
927                 }
928                 memcpy(shmem_file, response_file, fn_len );
929         } else {
930                 shmem_file=0;
931         }
932         /* HACK: there is yet a shortcoming -- if t_uac fails, callback
933            will not be triggered and no feedback will be printed
934            to shmem_file
935         */
936         dummy_empty.s=0; dummy_empty.len=0;
937         ret=t_uac_dlg( &method, 
938                 outbound.len ? &outbound: 0,
939                 &ruri, 
940                 &faked_msg.to->body,    /* possibly w/to-tag in it */
941                 &faked_msg.from->body,
942                 &dummy_empty,                   /* if present, to-tag passed in to */
943                 fromtag ?                               /* if fromtag present, ... */
944                         &dummy_empty:           /* ... pass it in from ... */
945                         0,                                      /* use ephemeral otherwise */
946                 cseq ? &cseq : 0,
947                 faked_msg.callid ?
948                         &faked_msg.callid->body:
949                         0,
950                 0,                                              /* headers -- TBD */
951                 &body,
952                 fifo_callback, shmem_file );
953
954
955         if (ret<=0) {
956                 err_ret=err2reason_phrase(ret, &sip_error, err_buf,
957                                 sizeof(err_buf), "FIFO/UAC" ) ;
958                 if (err_ret > 0 )
959                 {
960
961                         fifo_uac_error(response_file, sip_error, err_buf);
962                 } else {
963                         fifo_uac_error(response_file, 500, "FIFO/UAC error" );
964 #ifdef _OBSO
965                         fifo_reply(response_file, "500 FIFO/UAC error: %d\n",
966                                 ret );
967 #endif
968                 }
969         }
970
971 error:
972         free_sip_msg(&faked_msg);
973         return 1;
974 }