3-digit reply code introduced to FIFO server
[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
35 #include <stdlib.h>
36 #include <sys/types.h>
37 #include <unistd.h>
38 #include <stdio.h>
39 #include <errno.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <fcntl.h>
43 #include <signal.h>
44 #include "../../dprint.h"
45 #include "../../ut.h"
46 #include "../../hash_func.h"
47 #include "../../md5utils.h"
48 #include "../../mem/mem.h"
49 #include "../../fifo_server.h"
50 #include "../../error.h"
51 #include "t_funcs.h"
52 #include "config.h"
53 #include "sip_msg.h"
54 #include "ut.h"
55 #include "t_msgbuilder.h"
56 #include "uac.h"
57
58 /* Call-ID has the following form: call_id_rand-pid-seq */
59
60 char call_id[RAND_DIGITS+1+MAX_PID_LEN+1+MAX_SEQ_LEN+1];
61 static unsigned long callid_seq;
62
63 char *uac_from="\"UAC Account\" <sip:uac@dev.null:9>";
64
65 char from_tag[ MD5_LEN +1];
66
67 void uac_init() {
68         unsigned long init_nr;
69         char *c;
70         int len;
71
72         str src[3];
73
74         init_nr=random() % (1<<(RAND_DIGITS*4));
75         c=call_id;
76         len=RAND_DIGITS;
77         int2reverse_hex( &c, &len, init_nr );
78         while (len) { *c='z'; len--; c++; }
79         *c='-';
80
81         src[0].s="Long live SER server";
82         src[0].len=strlen(src[0].s);
83         src[1].s=sock_info[0].address_str.s;
84         src[1].len=strlen(src[1].s);
85         src[2].s=sock_info[0].port_no_str.s;
86         src[2].len=strlen(src[2].s);
87
88         MDStringArray( from_tag, src, 3 );
89         from_tag[MD5_LEN]=0;
90 }
91
92
93 void uac_child_init( int rank ) {
94         int pid_nr;
95         char *c;
96         int len;
97
98         pid_nr=getpid() % (1<<(MAX_PID_LEN*4));
99         c=call_id+RAND_DIGITS+1;
100         len=MAX_PID_LEN;
101         int2reverse_hex( &c, &len, pid_nr );
102         while (len) { *c='z'; len--; c++; }
103         *c='-';
104
105         callid_seq=random() % TABLE_ENTRIES;
106
107 }
108
109 void generate_callid() {
110         char *c;
111         int len;
112
113         /* HACK: not long enough */
114         callid_seq = (callid_seq+1) % TABLE_ENTRIES;
115         c=call_id+RAND_DIGITS+1+MAX_PID_LEN+1;
116         len=MAX_SEQ_LEN;
117         int2reverse_hex( &c, &len, callid_seq );
118         while (len) { *c='z'; len--; c++; }
119 }
120
121
122
123 int t_uac( str *msg_type, str *dst, 
124         str *headers, str *body, str *from, 
125         transaction_cb completion_cb, void *cbp, 
126         dlg_t dlg)
127 {
128
129         struct cell *new_cell;
130         struct proxy_l *proxy;
131         int branch;
132         int ret;
133         unsigned int req_len;
134         char *buf;
135         union sockaddr_union to;
136         struct socket_info* send_sock;
137         struct retr_buf *request;
138         str dummy_from;
139
140         proxy=uri2proxy( dst );
141         if (proxy==0) {
142                 ser_error=ret=E_BAD_ADDRESS;
143                 LOG(L_ERR, "ERROR: t_uac: can't create a dst proxy\n");
144                 goto done;
145         }
146         branch=0;
147         /* might go away -- we ignore it in send_pr_buffer anyway */
148         /* T->uac[branch].request.to_len=sizeof(union sockaddr_union); */
149         hostent2su(&to, &proxy->host, proxy->addr_idx, 
150                 (proxy->port)?htons(proxy->port):htons(SIP_PORT));
151         send_sock=get_send_socket( &to );
152         if (send_sock==0) {
153                 LOG(L_ERR, "ERROR: t_uac: no corresponding listening socket "
154                         "for af %d\n", to.s.sa_family );
155                 ret=E_NO_SOCKET;
156                 goto error00;
157         }
158         generate_callid();
159
160         new_cell = build_cell( NULL ) ; 
161         if (!new_cell) {
162                 ret=E_OUT_OF_MEM;
163                 LOG(L_ERR, "ERROR: t_uac: short of cell shmem\n");
164                 goto error00;
165         }
166         new_cell->completion_cb=completion_cb;
167         new_cell->cbp=cbp;
168         /* cbp is installed -- tell error handling bellow not to free it */
169         cbp=0;
170         new_cell->is_invite=msg_type->len==INVITE_LEN 
171                 && memcmp(msg_type->s, INVITE, INVITE_LEN)==0;
172         new_cell->local=1;
173         new_cell->kr=REQ_FWDED;
174
175
176         request=&new_cell->uac[branch].request;
177         request->to=to;
178         request->send_sock=send_sock;
179
180         /* need to put in table to calculate label which is needed for printing */
181         LOCK_HASH(new_cell->hash_index);
182         insert_into_hash_table_unsafe(  new_cell );
183         UNLOCK_HASH(new_cell->hash_index);
184
185         if (from) dummy_from=*from; else { dummy_from.s=0; dummy_from.len=0; }
186         buf=build_uac_request(  *msg_type, *dst, dummy_from, *headers, *body,
187                                                         branch,
188                                                         new_cell, /* t carries hash_index, label, md5,
189                                                                                 uac[].send_sock and other pieces of
190                                                                                 information needed to print a message*/
191                                                          &req_len );
192     if (!buf) {
193         ret=E_OUT_OF_MEM;
194         LOG(L_ERR, "ERROR: t_uac: short of req shmem\n");
195         goto error01;
196     }      
197         new_cell->method.s=buf;new_cell->method.len=msg_type->len;
198
199
200         request->buffer = buf;
201         request->buffer_len = req_len;
202         new_cell->nr_of_outgoings++;
203
204
205         proxy->tx++;
206         proxy->tx_bytes+=req_len;
207
208         if (SEND_BUFFER( request)==-1) {
209                 LOG(L_ERR, "ERROR: t_uac: UAC sending to %.*s failed\n",
210                         dst->len, dst->s );
211                 proxy->errors++;
212                 proxy->ok=0;
213         }
214         start_retr( request );
215
216         /* success */
217         return 1;
218
219 error01:
220         LOCK_HASH(new_cell->hash_index);
221         remove_from_hash_table_unsafe( new_cell );
222         UNLOCK_HASH(new_cell->hash_index);
223         free_cell(new_cell);
224 error00:
225         free_proxy( proxy );
226         free( proxy );
227 done: 
228         /* if we did not install cbp, release it now */
229         if (cbp) shm_free(cbp);
230         return ser_error=ret;
231 }
232
233 static void fifo_callback( struct cell *t, struct sip_msg *msg,
234         int code, void *param)
235 {
236
237         char *filename;
238         str text;
239
240         DBG("DEBUG: fifo UAC completed with status %d\n", code);
241         if (!t->cbp) {
242                 LOG(L_INFO, "INFO: fifo UAC completed with status %d\n", code);
243                 return;
244         }
245
246         filename=(char *)(t->cbp);
247         get_reply_status(&text,msg,code);
248         if (text.s==0) {
249                 LOG(L_ERR, "ERROR: fifo_callback: get_reply_status failed\n");
250                 fifo_reply(filename, "500 fifo_callback: get_reply_status failed\n");
251                 return;
252         }
253         fifo_reply(filename, "%.*s", text.len, text.s );
254         pkg_free(text.s);
255         DBG("DEBUG: fifo_callback sucesssfuly completed\n");
256 }       
257
258 /* to be obsoleted in favor of fifo_uac_from */
259 int fifo_uac( FILE *stream, char *response_file ) 
260 {
261         char method[MAX_METHOD];
262         char header[MAX_HEADER];
263         char body[MAX_BODY];
264         char dst[MAX_DST];
265         str sm, sh, sb, sd;
266         char *shmem_file;
267         int fn_len;
268         int ret;
269         int sip_error;
270         char err_buf[MAX_REASON_LEN];
271
272         sm.s=method; sh.s=header; sb.s=body; sd.s=dst;
273         if (!read_line(method, MAX_METHOD, stream,&sm.len)||sm.len==0) {
274                 /* line breaking must have failed -- consume the rest
275                    and proceed to a new request
276                 */
277                 LOG(L_ERR, "ERROR: fifo_uac: method expected\n");
278                 fifo_reply(response_file, 
279                         "400 fifo_uac: method expected");
280                 return 1;
281         }
282         DBG("DEBUG: fifo_uac: method: %.*s\n", sm.len, method );
283         if (!read_line(dst, MAX_DST, stream, &sd.len)||sd.len==0) {
284                 fifo_reply(response_file, 
285                         "400 fifo_uac: destination expected\n");
286                 LOG(L_ERR, "ERROR: fifo_uac: destination expected\n");
287                 return 1;
288         }
289         DBG("DEBUG: fifo_uac:  dst: %.*s\n", sd.len, dst );
290         /* now read header fields line by line */
291         if (!read_line_set(header, MAX_HEADER, stream, &sh.len)) {
292                 fifo_reply(response_file, 
293                         "400 fifo_uac: HFs expected\n");
294                 LOG(L_ERR, "ERROR: fifo_uac: header fields expected\n");
295                 return 1;
296         }
297         DBG("DEBUG: fifo_uac: header: %.*s\n", sh.len, header );
298         /* and eventually body */
299         if (!read_body(body, MAX_BODY, stream, &sb.len)) {
300                 fifo_reply(response_file, 
301                         "400 fifo_uac: body expected\n");
302                 LOG(L_ERR, "ERROR: fifo_uac: body expected\n");
303                 return 1;
304         }
305         DBG("DEBUG: fifo_uac: body: %.*s\n", sb.len, body );
306         DBG("DEBUG: fifo_uac: EoL -- proceeding to transaction creation\n");
307         /* we got it all, initiate transaction now! */
308         if (response_file) {
309                 fn_len=strlen(response_file)+1;
310                 shmem_file=shm_malloc(fn_len);
311                 if (shmem_file==0) {
312                         LOG(L_ERR, "ERROR: fifo_uac: no shmem\n");
313                         fifo_reply(response_file, 
314                                 "500 fifo_uac: no shmem for shmem_file\n");
315                         return 1;
316                 }
317                 memcpy(shmem_file, response_file, fn_len );
318         } else {
319                 shmem_file=0;
320         }
321         ret=t_uac(&sm,&sd,&sh,&sb, 0 /* default from */,
322                 fifo_callback,shmem_file,0 /* no dialog */);
323         if (ret>0) {
324                 if (err2reason_phrase(ret, &sip_error, err_buf,
325                                 sizeof(err_buf), "FIFO/UAC" ) > 0 ) 
326                 {
327                         fifo_reply(response_file, "500 FIFO/UAC error: %d\n",
328                                 ret );
329                 } else {
330                         fifo_reply(response_file, err_buf );
331                 }
332         }
333         return 1;
334 }
335
336 /* syntax:
337
338         :t_uac_from:[file] EOL
339         method EOL
340         [from] EOL (if none, server's default from is taken)
341         dst EOL (put in r-uri and To)
342         [CR-LF separated HFs]* EOL
343         EOL
344         [body] EOL
345         EOL
346
347 */
348
349 int fifo_uac_from( FILE *stream, char *response_file ) 
350 {
351         char method[MAX_METHOD];
352         char header[MAX_HEADER];
353         char body[MAX_BODY];
354         char dst[MAX_DST];
355         char from[MAX_FROM];
356         str sm, sh, sb, sd, sf;
357         char *shmem_file;
358         int fn_len;
359         int ret;
360         int sip_error;
361         char err_buf[MAX_REASON_LEN];
362         int err_ret;
363
364         sm.s=method; sh.s=header; sb.s=body; sd.s=dst;sf.s=from;
365
366         if (!read_line(method, MAX_METHOD, stream,&sm.len)||sm.len==0) {
367                 /* line breaking must have failed -- consume the rest
368                    and proceed to a new request
369                 */
370                 LOG(L_ERR, "ERROR: fifo_uac: method expected\n");
371                 fifo_reply(response_file, 
372                         "400 fifo_uac: method expected");
373                 return 1;
374         }
375         DBG("DEBUG: fifo_uac: method: %.*s\n", sm.len, method );
376         if (!read_line(from, MAX_FROM, stream, &sf.len)) {
377                 fifo_reply(response_file, 
378                         "400 fifo_uac: from expected\n");
379                 LOG(L_ERR, "ERROR: fifo_uac: from expected\n");
380                 return 1;
381         }
382         DBG("DEBUG: fifo_uac:  from: %.*s\n", sf.len, from);
383         if (!read_line(dst, MAX_DST, stream, &sd.len)||sd.len==0) {
384                 fifo_reply(response_file, 
385                         "400 fifo_uac: destination expected\n");
386                 LOG(L_ERR, "ERROR: fifo_uac: destination expected\n");
387                 return 1;
388         }
389         DBG("DEBUG: fifo_uac:  dst: %.*s\n", sd.len, dst );
390         /* now read header fields line by line */
391         if (!read_line_set(header, MAX_HEADER, stream, &sh.len)) {
392                 fifo_reply(response_file, 
393                         "400 fifo_uac: HFs expected\n");
394                 LOG(L_ERR, "ERROR: fifo_uac: header fields expected\n");
395                 return 1;
396         }
397         DBG("DEBUG: fifo_uac: header: %.*s\n", sh.len, header );
398         /* and eventually body */
399         if (!read_body(body, MAX_BODY, stream, &sb.len)) {
400                 fifo_reply(response_file, 
401                         "400 fifo_uac: body expected\n");
402                 LOG(L_ERR, "ERROR: fifo_uac: body expected\n");
403                 return 1;
404         }
405         DBG("DEBUG: fifo_uac: body: %.*s\n", sb.len, body );
406         DBG("DEBUG: fifo_uac: EoL -- proceeding to transaction creation\n");
407         /* we got it all, initiate transaction now! */
408         if (response_file) {
409                 fn_len=strlen(response_file)+1;
410                 shmem_file=shm_malloc(fn_len);
411                 if (shmem_file==0) {
412                         LOG(L_ERR, "ERROR: fifo_uac: no shmem\n");
413                         fifo_reply(response_file, 
414                                 "500 fifo_uac: no memory for shmem_file\n");
415                         return 1;
416                 }
417                 memcpy(shmem_file, response_file, fn_len );
418         } else {
419                 shmem_file=0;
420         }
421         /* HACK: there is yet a shortcoming -- if t_uac fails, callback
422            will not be triggered and no feedback will be printed
423            to shmem_file
424         */
425         ret=t_uac(&sm,&sd,&sh,&sb, sf.len==0 ? 0 : &sf /* default from */,
426                 fifo_callback,shmem_file,0 /* no dialog */);
427         if (ret<=0) {
428                 err_ret=err2reason_phrase(ret, &sip_error, err_buf,
429                                 sizeof(err_buf), "FIFO/UAC" ) ;
430                 if (err_ret > 0 )
431                 {
432                         fifo_reply(response_file, err_buf );
433                 } else {
434                         fifo_reply(response_file, "500 FIFO/UAC error: %d\n",
435                                 ret );
436                 }
437         }
438         return 1;
439
440 }