feb1f7eeda4dddc09ad924147899c10e74f0a977
[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         /* be optimist -- assume success for return value */
117         ret=1;
118
119         proxy=uri2proxy( dst );
120         if (proxy==0) {
121                 ser_error=ret=E_BAD_ADDRESS;
122                 LOG(L_ERR, "ERROR: t_uac: can't create a dst proxy\n");
123                 goto done;
124         }
125         branch=0;
126         /* might go away -- we ignore it in send_pr_buffer anyway */
127         /* T->uac[branch].request.to_len=sizeof(union sockaddr_union); */
128         hostent2su(&to, &proxy->host, proxy->addr_idx, 
129                 (proxy->port)?htons(proxy->port):htons(SIP_PORT));
130         send_sock=get_send_socket( &to );
131         if (send_sock==0) {
132                 LOG(L_ERR, "ERROR: t_uac: no corresponding listening socket "
133                         "for af %d\n", to.s.sa_family );
134                 ret=E_NO_SOCKET;
135                 goto error00;
136         }
137         generate_callid();
138
139         new_cell = build_cell( NULL ) ; 
140         if (!new_cell) {
141                 ret=E_OUT_OF_MEM;
142                 LOG(L_ERR, "ERROR: t_uac: short of cell shmem\n");
143                 goto error00;
144         }
145         new_cell->completion_cb=completion_cb;
146         new_cell->cbp=cbp;
147         /* cbp is installed -- tell error handling bellow not to free it */
148         cbp=0;
149         new_cell->is_invite=msg_type->len==INVITE_LEN 
150                 && memcmp(msg_type->s, INVITE, INVITE_LEN)==0;
151         new_cell->local=1;
152         LOCK_HASH(new_cell->hash_index);
153         insert_into_hash_table_unsafe(  new_cell );
154         UNLOCK_HASH(new_cell->hash_index);
155
156         request=&new_cell->uac[branch].request;
157         request->to=to;
158         request->send_sock=send_sock;
159
160         if (from) dummy_from=*from; else { dummy_from.s=0; dummy_from.len=0; }
161         buf=build_uac_request(  *msg_type, *dst, dummy_from, *headers, *body, branch,
162                 new_cell /* t carries hash_index, label, md5, uac[].send_sock and
163                      other pieces of information needed to print a message*/
164                 , &req_len );
165     if (!buf) {
166         ret=E_OUT_OF_MEM;
167         LOG(L_ERR, "ERROR: t_uac: short of req shmem\n");
168         goto error01;
169     }      
170         new_cell->method.s=buf;new_cell->method.len=msg_type->len;
171
172         request->buffer = buf;
173         request->buffer_len = req_len;
174         new_cell->nr_of_outgoings++;
175
176         proxy->tx++;
177         proxy->tx_bytes+=req_len;
178
179         if (SEND_BUFFER( request)==-1) {
180                 LOG(L_ERR, "ERROR: t_uac: UAC sending to %.*s failed\n",
181                         dst->len, dst->s );
182                 proxy->errors++;
183                 proxy->ok=0;
184                 ser_error=ret=E_SEND;
185                 goto error01;
186         }
187         new_cell->kr=REQ_FWDED;
188         start_retr( request );
189
190         /* success */
191         goto done;
192
193 error01: 
194         /* this is the safest way (though not the cheapest) to
195            make a transaction disappear; we may appreciate the
196            safety later when we add more complexity
197         */
198         cleanup_uac_timers(new_cell);
199         put_on_wait(new_cell);
200 error00:
201         free_proxy( proxy );
202         free( proxy );
203 done: 
204         /* if we did not install cbp, release it now */
205         if (cbp) shm_free(cbp);
206         return ser_error=ret;
207 }
208
209 static void fifo_callback( struct cell *t, struct sip_msg *msg,
210         int code, void *param)
211 {
212
213         char *filename;
214         str text;
215
216         DBG("DEBUG: fifo UAC completed with status %d\n", code);
217         if (!t->cbp) {
218                 LOG(L_INFO, "INFO: fifo UAC completed with status %d\n", code);
219                 return;
220         }
221
222         filename=(char *)(t->cbp);
223         get_reply_status(&text,msg,code);
224         if (text.s==0) {
225                 LOG(L_ERR, "ERROR: fifo_callback: get_reply_status failed\n");
226                 fifo_reply(filename, "ERROR: fifo_callback: get_reply_status failed\n");
227                 return;
228         }
229         fifo_reply(filename, "%.*s", text.len, text.s );
230         pkg_free(text.s);
231         DBG("DEBUG: fifo_callback sucesssfuly completed\n");
232 }       
233
234 /* to be obsoleted in favor of fifo_uac_from */
235 int fifo_uac( FILE *stream, char *response_file ) 
236 {
237         char method[MAX_METHOD];
238         char header[MAX_HEADER];
239         char body[MAX_BODY];
240         char dst[MAX_DST];
241         str sm, sh, sb, sd;
242         char *shmem_file;
243         int fn_len;
244
245         sm.s=method; sh.s=header; sb.s=body; sd.s=dst;
246         while(1) {
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                 /* HACK: there is yet a shortcoming -- if t_uac fails, callback
294                    will not be triggered and no feedback will be printed
295                    to shmem_file
296                 */
297                 t_uac(&sm,&sd,&sh,&sb, 0 /* default from */,
298                         fifo_callback,shmem_file,0 /* no dialog */);
299                 return 1;
300
301         }
302 }
303
304 /* syntax:
305
306         :t_uac_from:[file] EOL
307         method EOL
308         [from] EOL (if none, server's default from is taken)
309         dst EOL (put in r-uri and To)
310         [CR-LF separated HFs]* EOL
311         EOL
312         [body] EOL
313         EOL
314
315 */
316
317 int fifo_uac_from( FILE *stream, char *response_file ) 
318 {
319         char method[MAX_METHOD];
320         char header[MAX_HEADER];
321         char body[MAX_BODY];
322         char dst[MAX_DST];
323         char from[MAX_FROM];
324         str sm, sh, sb, sd, sf;
325         char *shmem_file;
326         int fn_len;
327
328         sm.s=method; sh.s=header; sb.s=body; sd.s=dst;sf.s=from;
329         while(1) {
330                 if (!read_line(method, MAX_METHOD, stream,&sm.len)||sm.len==0) {
331                         /* line breaking must have failed -- consume the rest
332                            and proceed to a new request
333                         */
334                         LOG(L_ERR, "ERROR: fifo_uac: method expected\n");
335                         fifo_reply(response_file, 
336                                 "ERROR: fifo_uac: method expected");
337                         return -1;
338                 }
339                 DBG("DEBUG: fifo_uac: method: %.*s\n", sm.len, method );
340                 if (!read_line(from, MAX_FROM, stream, &sf.len)) {
341                         fifo_reply(response_file, 
342                                 "ERROR: fifo_uac: from expected\n");
343                         LOG(L_ERR, "ERROR: fifo_uac: from expected\n");
344                         return -1;
345                 }
346                 DBG("DEBUG: fifo_uac:  from: %.*s\n", sf.len, from);
347                 if (!read_line(dst, MAX_DST, stream, &sd.len)||sd.len==0) {
348                         fifo_reply(response_file, 
349                                 "ERROR: fifo_uac: destination expected\n");
350                         LOG(L_ERR, "ERROR: fifo_uac: destination expected\n");
351                         return -1;
352                 }
353                 DBG("DEBUG: fifo_uac:  dst: %.*s\n", sd.len, dst );
354                 /* now read header fields line by line */
355                 if (!read_line_set(header, MAX_HEADER, stream, &sh.len)) {
356                         fifo_reply(response_file, 
357                                 "ERROR: fifo_uac: HFs expected\n");
358                         LOG(L_ERR, "ERROR: fifo_uac: header fields expected\n");
359                         return -1;
360                 }
361                 DBG("DEBUG: fifo_uac: header: %.*s\n", sh.len, header );
362                 /* and eventually body */
363                 if (!read_body(body, MAX_BODY, stream, &sb.len)) {
364                         fifo_reply(response_file, 
365                                 "ERROR: fifo_uac: body expected\n");
366                         LOG(L_ERR, "ERROR: fifo_uac: body expected\n");
367                         return -1;
368                 }
369                 DBG("DEBUG: fifo_uac: body: %.*s\n", sb.len, body );
370                 DBG("DEBUG: fifo_uac: EoL -- proceeding to transaction creation\n");
371                 /* we got it all, initiate transaction now! */
372                 if (response_file) {
373                         fn_len=strlen(response_file)+1;
374                         shmem_file=shm_malloc(fn_len);
375                         if (shmem_file==0) {
376                                 LOG(L_ERR, "ERROR: fifo_uac: no shmem\n");
377                                 return -1;
378                         }
379                         memcpy(shmem_file, response_file, fn_len );
380                 } else {
381                         shmem_file=0;
382                 }
383                 /* HACK: there is yet a shortcoming -- if t_uac fails, callback
384                    will not be triggered and no feedback will be printed
385                    to shmem_file
386                 */
387                 t_uac(&sm,&sd,&sh,&sb, sf.len==0 ? 0 : &sf /* default from */,
388                         fifo_callback,shmem_file,0 /* no dialog */);
389                 return 1;
390
391         }
392 }