fixed missing t->kr in t_uac
[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         int file;
215         int r;
216         str text;
217
218         DBG("DEBUG: fifo UAC completed with status %d\n", code);
219         if (t->cbp) {
220                 filename=(char *)(t->cbp);
221                 file=open(filename, O_WRONLY);
222                 if (file<0) {
223                         LOG(L_ERR, "ERROR: fifo_callback: can't open file %s: %s\n",
224                                 filename, strerror(errno));
225                         return;
226                 }
227                 get_reply_status(&text,msg,code);
228                 if (text.s==0) {
229                         LOG(L_ERR, "ERROR: fifo_callback: get_reply_status failed\n");
230                         return;
231                 }
232                 r=write(file, text.s , text.len );
233                 close(file);
234                 pkg_free(text.s);
235                 if (r<0) {
236                         LOG(L_ERR, "ERROR: fifo_callback: write error: %s\n",
237                                 strerror(errno));
238                         return; 
239                 }
240         } else {
241                 LOG(L_INFO, "INFO: fifo UAC completed with status %d\n", code);
242         }
243 }       
244
245 /* to be obsoleted in favor of fifo_uac_from */
246 int fifo_uac( FILE *stream, char *response_file ) 
247 {
248         char method[MAX_METHOD];
249         char header[MAX_HEADER];
250         char body[MAX_BODY];
251         char dst[MAX_DST];
252         str sm, sh, sb, sd;
253         char *shmem_file;
254         int fn_len;
255
256         sm.s=method; sh.s=header; sb.s=body; sd.s=dst;
257         while(1) {
258                 if (!read_line(method, MAX_METHOD, stream,&sm.len)||sm.len==0) {
259                         /* line breaking must have failed -- consume the rest
260                            and proceed to a new request
261                         */
262                         LOG(L_ERR, "ERROR: fifo_uac: method expected\n");
263                         fifo_reply(response_file, 
264                                 "ERROR: fifo_uac: method expected");
265                         return -1;
266                 }
267                 DBG("DEBUG: fifo_uac: method: %.*s\n", sm.len, method );
268                 if (!read_line(dst, MAX_DST, stream, &sd.len)||sd.len==0) {
269                         fifo_reply(response_file, 
270                                 "ERROR: fifo_uac: destination expected\n");
271                         LOG(L_ERR, "ERROR: fifo_uac: destination expected\n");
272                         return -1;
273                 }
274                 DBG("DEBUG: fifo_uac:  dst: %.*s\n", sd.len, dst );
275                 /* now read header fields line by line */
276                 if (!read_line_set(header, MAX_HEADER, stream, &sh.len)) {
277                         fifo_reply(response_file, 
278                                 "ERROR: fifo_uac: HFs expected\n");
279                         LOG(L_ERR, "ERROR: fifo_uac: header fields expected\n");
280                         return -1;
281                 }
282                 DBG("DEBUG: fifo_uac: header: %.*s\n", sh.len, header );
283                 /* and eventually body */
284                 if (!read_body(body, MAX_BODY, stream, &sb.len)) {
285                         fifo_reply(response_file, 
286                                 "ERROR: fifo_uac: body expected\n");
287                         LOG(L_ERR, "ERROR: fifo_uac: body expected\n");
288                         return -1;
289                 }
290                 DBG("DEBUG: fifo_uac: body: %.*s\n", sb.len, body );
291                 DBG("DEBUG: fifo_uac: EoL -- proceeding to transaction creation\n");
292                 /* we got it all, initiate transaction now! */
293                 if (response_file) {
294                         fn_len=strlen(response_file)+1;
295                         shmem_file=shm_malloc(fn_len);
296                         if (shmem_file==0) {
297                                 LOG(L_ERR, "ERROR: fifo_uac: no shmem\n");
298                                 return -1;
299                         }
300                         memcpy(shmem_file, response_file, fn_len );
301                 } else {
302                         shmem_file=0;
303                 }
304                 /* HACK: there is yet a shortcoming -- if t_uac fails, callback
305                    will not be triggered and no feedback will be printed
306                    to shmem_file
307                 */
308                 t_uac(&sm,&sd,&sh,&sb, 0 /* default from */,
309                         fifo_callback,shmem_file,0 /* no dialog */);
310                 return 1;
311
312         }
313 }
314
315 /* syntax:
316
317         :t_uac_from:[file] EOL
318         method EOL
319         [from] EOL (if none, server's default from is taken)
320         dst EOL (put in r-uri and To)
321         [CR-LF separated HFs]* EOL
322         EOL
323         [body] EOL
324         EOL
325
326 */
327
328 int fifo_uac_from( FILE *stream, char *response_file ) 
329 {
330         char method[MAX_METHOD];
331         char header[MAX_HEADER];
332         char body[MAX_BODY];
333         char dst[MAX_DST];
334         char from[MAX_FROM];
335         str sm, sh, sb, sd, sf;
336         char *shmem_file;
337         int fn_len;
338
339         sm.s=method; sh.s=header; sb.s=body; sd.s=dst;sf.s=from;
340         while(1) {
341                 if (!read_line(method, MAX_METHOD, stream,&sm.len)||sm.len==0) {
342                         /* line breaking must have failed -- consume the rest
343                            and proceed to a new request
344                         */
345                         LOG(L_ERR, "ERROR: fifo_uac: method expected\n");
346                         fifo_reply(response_file, 
347                                 "ERROR: fifo_uac: method expected");
348                         return -1;
349                 }
350                 DBG("DEBUG: fifo_uac: method: %.*s\n", sm.len, method );
351                 if (!read_line(from, MAX_FROM, stream, &sf.len)) {
352                         fifo_reply(response_file, 
353                                 "ERROR: fifo_uac: from expected\n");
354                         LOG(L_ERR, "ERROR: fifo_uac: from expected\n");
355                         return -1;
356                 }
357                 DBG("DEBUG: fifo_uac:  from: %.*s\n", sf.len, from);
358                 if (!read_line(dst, MAX_DST, stream, &sd.len)||sd.len==0) {
359                         fifo_reply(response_file, 
360                                 "ERROR: fifo_uac: destination expected\n");
361                         LOG(L_ERR, "ERROR: fifo_uac: destination expected\n");
362                         return -1;
363                 }
364                 DBG("DEBUG: fifo_uac:  dst: %.*s\n", sd.len, dst );
365                 /* now read header fields line by line */
366                 if (!read_line_set(header, MAX_HEADER, stream, &sh.len)) {
367                         fifo_reply(response_file, 
368                                 "ERROR: fifo_uac: HFs expected\n");
369                         LOG(L_ERR, "ERROR: fifo_uac: header fields expected\n");
370                         return -1;
371                 }
372                 DBG("DEBUG: fifo_uac: header: %.*s\n", sh.len, header );
373                 /* and eventually body */
374                 if (!read_body(body, MAX_BODY, stream, &sb.len)) {
375                         fifo_reply(response_file, 
376                                 "ERROR: fifo_uac: body expected\n");
377                         LOG(L_ERR, "ERROR: fifo_uac: body expected\n");
378                         return -1;
379                 }
380                 DBG("DEBUG: fifo_uac: body: %.*s\n", sb.len, body );
381                 DBG("DEBUG: fifo_uac: EoL -- proceeding to transaction creation\n");
382                 /* we got it all, initiate transaction now! */
383                 if (response_file) {
384                         fn_len=strlen(response_file)+1;
385                         shmem_file=shm_malloc(fn_len);
386                         if (shmem_file==0) {
387                                 LOG(L_ERR, "ERROR: fifo_uac: no shmem\n");
388                                 return -1;
389                         }
390                         memcpy(shmem_file, response_file, fn_len );
391                 } else {
392                         shmem_file=0;
393                 }
394                 /* HACK: there is yet a shortcoming -- if t_uac fails, callback
395                    will not be triggered and no feedback will be printed
396                    to shmem_file
397                 */
398                 t_uac(&sm,&sd,&sh,&sb, sf.len==0 ? 0 : &sf /* default from */,
399                         fifo_callback,shmem_file,0 /* no dialog */);
400                 return 1;
401
402         }
403 }