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