ser_error processing, ipv6-ization of TM, new TM callbacks;
[sip-router] / modules / tm / t_fwd.c
1 /*
2  * $Id$
3  *
4  */
5
6 #include "../../dprint.h"
7 #include "../../config.h"
8 #include "../../parser/parser_f.h"
9 #include "../../ut.h"
10 #include "../../timer.h"
11 #include "hash_func.h"
12 #include "t_funcs.h"
13 #include "t_fork.h"
14
15 #include "t_hooks.h"
16
17
18 #define shm_free_lump( _lmp) \
19         do{\
20                 if ((_lmp)) {\
21                         if ((_lmp)->op==LUMP_ADD && (_lmp)->u.value )\
22                                 shm_free((_lmp)->u.value);\
23                         shm_free((_lmp));\
24                 }\
25         }while(0);
26
27
28
29 /* function returns:
30  *       1 - forward successfull
31  *      -1 - error during forward
32  */
33 int t_forward_nonack( struct sip_msg* p_msg , 
34                                           struct proxy_l * p )
35 /* v6; -jiri                                                                    unsigned int dest_ip_param ,
36                                                                                                 unsigned int dest_port_param )
37 */
38 {
39         int          branch;
40         unsigned int len;
41         char         *buf, *shbuf;
42         struct cell  *T_source = T;
43         struct lump  *a,*b,*b1,*c;
44         str          backup_uri;
45         int                      ret;
46         struct socket_info* send_sock;
47         union sockaddr_union to;
48
49
50         /* default error value == -1; be more specific if you want to */
51         ret=-1;
52         buf    = 0;
53         shbuf  = 0;
54         backup_uri.s = p_msg->new_uri.s;
55         backup_uri.len = p_msg->new_uri.len;
56
57
58
59         /* are we forwarding for the first time? */
60         if ( T->uac[0].request.buffer )
61         {       /* rewriting a request should really not happen -- retransmission
62                    does not rewrite, whereas a new request should be written
63                    somewhere else */
64                 LOG( L_CRIT, "ERROR: t_forward_nonack: attempt to rewrite"
65                         " request structures\n");
66                 ser_error=E_BUG;
67                 return 0;
68         }
69
70         /* v6; -jiri ... copynpasted from forward_request */
71         /* if error try next ip address if possible */
72         if (p->ok==0){
73                 if (p->host.h_addr_list[p->addr_idx+1])
74                         p->addr_idx++;
75                 else p->addr_idx=0;
76                 p->ok=1;
77         }
78         hostent2su(&to, &p->host, p->addr_idx,
79         (p->port)?htons(p->port):htons(SIP_PORT));
80
81         /* sets as first fork the default outgoing */
82         nr_forks++;
83         /* v6; -jiri
84         t_forks[0].ip = dest_ip_param;
85         t_forks[0].port = dest_port_param;
86         */
87         t_forks[0].to=to;
88         t_forks[0].uri.len = p_msg->new_uri.len;
89         t_forks[0].uri.s =  p_msg->new_uri.s;
90         t_forks[0].free_flag = 0;
91
92         DBG("DEBUG: t_forward_nonack: first time forwarding\n");
93         /* special case : CANCEL */
94         if ( p_msg->REQ_METHOD==METHOD_CANCEL  )
95         {
96                 DBG("DEBUG: t_forward_nonack: it's CANCEL\n");
97                 /* find original cancelled transaction; if found, use its
98                    next-hops; otherwise use those passed by script */
99                 if ( T->T_canceled==T_UNDEFINED )
100                         T->T_canceled = t_lookupOriginalT( hash_table , p_msg );
101                 /* if found */
102                 if ( T->T_canceled!=T_NULL )
103                 {
104                         for(nr_forks=0;nr_forks<T->T_canceled->nr_of_outgoings;nr_forks++)
105                         {
106                                 /* if in 1xx status, send to the same destination */
107                                 if ( (T->T_canceled->uac[nr_forks].status/100)==1 )
108                                 {
109                                         DBG("DEBUG: t_forward_nonack: branch %d not finalize"
110                                                 ": sending CANCEL for it\n",nr_forks);
111                                         /* v6; -jiri
112                                         t_forks[nr_forks].ip =
113                                           T->T_canceled->uac[nr_forks].request.to.sin_addr.s_addr; 
114                                         t_forks[nr_forks].port =
115                                           T->T_canceled->uac[nr_forks].request.to.sin_port;
116                                         */
117                                         t_forks[nr_forks].to = T->T_canceled->uac[nr_forks].request.to;
118
119                                         t_forks[nr_forks].uri.len =
120                                           T->T_canceled->uac[nr_forks].uri.len;
121                                         t_forks[nr_forks].uri.s =
122                                           T->T_canceled->uac[nr_forks].uri.s;
123                                         t_forks[nr_forks].free_flag = 0;
124                                 }else{
125                                         /* transaction exists, but nothing to cancel */
126                                         DBG("DEBUG: t_forward_nonack: branch %d finalized"
127                                                 ": no CANCEL sent here\n",nr_forks);
128                                         /* -v6; -jiri
129                                         t_forks[nr_forks].ip = 0;
130                                         */
131                                         t_forks[nr_forks].inactive= 1;
132                                 }
133                         }
134 #ifdef USE_SYNONIM
135                         T_source = T->T_canceled;
136                         T->label  = T->T_canceled->label;
137 #endif
138                 } else { /* transaction doesnot exists  */
139                         DBG("DEBUG: t_forward_nonack: canceled request not found! "
140                         "nothing to CANCEL\n");
141                 }
142         }/* end special case CANCEL*/
143
144 #ifndef USE_SYNONIM
145         branch=0;
146         if ( nr_forks && add_branch_label( T_source, T->uas.request , branch )==-1)
147                 goto error;
148 #endif
149
150         DBG("DEBUG: t_forward_nonack: nr_forks=%d\n",nr_forks);
151         for(branch=0;branch<nr_forks;branch++)
152         {
153                 /* -v6; -jiri if (!t_forks[branch].ip) */
154                 if (t_forks[branch].inactive)
155                         goto end_loop;
156                 DBG("DEBUG: t_forward_nonack: branch = %d\n",branch);
157                 /*generates branch param*/
158                 if ( add_branch_label( T_source, p_msg , branch )==-1)
159                         goto error;
160                 /* remove all the HDR_VIA type lumps */
161                 if (branch)
162                         for(b=p_msg->add_rm,b1=0;b;b1=b,b=b->next)
163                                 if (b->type==HDR_VIA)
164                                 {
165                                         for(a=b->before;a;)
166                                                 {c=a->before;free_lump(a);pkg_free(a);a=c;}
167                                         for(a=b->after;a;)
168                                                 {c=a->after;free_lump(a);pkg_free(a);a=c;}
169                                         if (b1) b1->next = b->next;
170                                                 else p_msg->add_rm = b->next;
171                                         free_lump(b);pkg_free(b);
172                                 }
173                 /* updates the new uri*/
174                 p_msg->new_uri.s = t_forks[branch].uri.s;
175                 p_msg->new_uri.len = t_forks[branch].uri.len;
176
177                 T->uac[branch].request.to = t_forks[branch].to;
178                 send_sock=get_send_socket( & T->uac[branch].request.to );
179                 if (send_sock==0) {
180                         LOG(L_ERR, "ERROR: t_forward_nonack: can't fwd to af %d "
181                                 "no corresponding listening socket\n", 
182                                 T->uac[branch].request.to.s.sa_family);
183                         ser_error=E_NO_SOCKET;
184                         goto error;
185                 }
186                 T->uac[branch].request.send_sock=send_sock;
187                 
188                 callback_event( TMCB_REQUEST_OUT, p_msg );      
189                 /* _test_insert_to_reply(p_msg, "Foo: Bar\r\n");*/
190                 if ( !(buf = build_req_buf_from_sip_req  ( p_msg, &len, send_sock ))) {
191                         ser_error=ret=E_OUT_OF_MEM;
192                         goto error;
193                 }
194                 /* allocates a new retrans_buff for the outbound request */
195                 DBG("DEBUG: t_forward_nonack: building outbound request"
196                         " for branch %d.\n",branch);
197                 shbuf = (char *) shm_malloc( len );
198                 if (!shbuf)
199                 {
200                         LOG(L_ERR, "ERROR: t_forward_nonack: out of shmem buffer\n");
201                         ser_error=ret=E_OUT_OF_MEM;
202                         goto error;
203                 }
204                 T->uac[branch].request.buffer = shbuf;
205                 T->uac[branch].request.buffer_len = len ;
206                 memcpy( T->uac[branch].request.buffer , buf , len );
207                 /* keeps a hooker to uri inside buffer*/
208                 T->uac[branch].uri.s = T->uac[branch].request.buffer +
209                         (p_msg->first_line.u.request.uri.s - p_msg->buf);
210                 T->uac[branch].uri.len=t_forks[branch].uri.s?(t_forks[branch].uri.len)
211                         :(p_msg->first_line.u.request.uri.len);
212                 /* send the request */
213                 /* v6; -jiri
214                 T->uac[branch].request.to.sin_addr.s_addr = t_forks[branch].ip;
215                 T->uac[branch].request.to.sin_port = t_forks[branch].port;
216                 T->uac[branch].request.to.sin_family = AF_INET;
217                 */
218                 T->uac[branch].request.to = t_forks[branch].to;
219                 p->tx++;
220                 p->tx_bytes+=len;
221                 if (SEND_BUFFER( &(T->uac[branch].request) )==-1) {
222                         p->errors++;
223                         p->ok=0;
224                         ser_error=ret=E_SEND;
225                         goto error;
226                 }
227                 /* should have p->errors++; p->ok=0; on error here... */
228
229
230                 pkg_free( buf ) ;
231                 buf=NULL;
232
233                 DBG("DEBUG: t_forward_nonack: starting timers (retrans and FR) %d\n",
234                         get_ticks() );
235                 /*sets and starts the FINAL RESPONSE timer */
236                 set_timer( hash_table, &(T->uac[branch].request.fr_timer),
237                 /*p_msg->REQ_METHOD==METHOD_INVITE?FR_INV_TIMER_LIST:FR_TIMER_LIST);*/
238                         FR_TIMER_LIST ); 
239                 /* sets and starts the RETRANS timer */
240                 T->uac[branch].request.retr_list = RT_T1_TO_1;
241                 set_timer( hash_table, &(T->uac[branch].request.retr_timer),
242                         RT_T1_TO_1 );
243                 end_loop:
244                 T->nr_of_outgoings++ ;
245                 DBG("DEBUG: branch %d done; outgoing uri=|%.*s|\n",branch,
246                         T->uac[branch].uri.len,T->uac[branch].uri.s);
247         }
248
249         /* if we have a branch spec. for NO_RESPONSE_RECEIVED, we have to 
250         move it immediatly after the last parallel branch */
251         /* v6; -jiri 
252         if (t_forks[NO_RPL_BRANCH].ip && T->nr_of_outgoings!=NO_RPL_BRANCH ) */
253         if (!t_forks[NO_RPL_BRANCH].inactive && T->nr_of_outgoings!=NO_RPL_BRANCH )
254         {
255                 branch = T->nr_of_outgoings;
256                 /* v6; -jiri
257                 T->uac[branch].request.to.sin_addr.s_addr = t_forks[NO_RPL_BRANCH].ip;
258                 T->uac[branch].request.to.sin_port = t_forks[NO_RPL_BRANCH].port;
259                 */
260                 T->uac[branch].request.to = t_forks[NO_RPL_BRANCH].to;
261
262                 T->uac[branch].uri.s = t_forks[NO_RPL_BRANCH].uri.s;
263                 T->uac[branch].uri.len = t_forks[NO_RPL_BRANCH].uri.len;
264         }
265         p_msg->new_uri.s = backup_uri.s;
266         p_msg->new_uri.len = backup_uri.len;
267         t_clear_forks();
268         return 1;
269
270 error:
271         if (shbuf) shm_free(shbuf);
272         T->uac[branch].request.buffer=NULL;
273         if (buf) pkg_free( buf );
274         p_msg->new_uri.s = backup_uri.s;
275         p_msg->new_uri.len = backup_uri.len;
276         t_clear_forks();
277         return ret;
278 }
279
280
281 #ifdef _YOU_DONT_REALLY_WANT_THIS
282
283 int t_forward_ack( struct sip_msg* p_msg  )
284 {
285         int branch;
286         unsigned int len;
287         char *buf, *ack;
288
289         /* drop local ACKs */
290         if (T->uas.status/100!=2 ) {
291                 DBG("DEBUG: t_forward_ACK:  local ACK dropped\n");
292                 return 1;
293         }
294
295         branch=T->relaied_reply_branch;
296         /* double-check for odd relaying */
297         if ( branch <0 || branch>=T->nr_of_outgoings ) {
298                 DBG("DEBUG: t_forward_ack: strange relaied_reply_branch:"
299                         " %d out of %d\n",branch, T->nr_of_outgoings );
300                 return -1;
301         }
302
303         DBG("DEBUG: t_forward_ack: forwarding ACK [%d]\n",branch);
304         /* not able to build branch -- then better give up */
305         if ( add_branch_label( T, p_msg , branch )==-1) {
306                 LOG( L_ERR, "ERROR: t_forward_ack failed to add branch label\n" );
307                 return 0;
308         }
309         /* not able to build outbound request -- then better give up */
310         if ( !(buf = build_req_buf_from_sip_req  ( p_msg, &len)))  {
311                 LOG(L_ERR,"ERROR: t_forward_ack failed to generate outbound ACK\n");
312                 return 0;
313         };
314
315 #ifdef _DONT_USE
316         /* strange conditions -- no INVITE before me ?!?! */
317         if ( (rb=T->outbound_request[branch])==NULL ) {
318                 /* better stateless than nothing */
319                 goto fwd_sl;
320         }
321 #endif
322
323         /* check for bizzar race condition if two processes receive
324            two ACKs concurrently; use shmem semaphore for protection
325            -- we have to enter it here anyway (the trick with inACKed
326            inside the protection region) */
327         if  (T->uas.isACKed ) {
328                 LOG(L_WARN,"Warning: ACK received when there's one; check upstream\n");
329                 return 1;
330         }
331         ack = shm_malloc( len );
332         memcpy(ack , buf , len);
333         pkg_free( buf );
334
335         T->uas.isACKed = 1;
336         SEND_PR_BUFFER( &(T->uac[branch].request), ack, len );
337         callback_event( TMCB_E2EACK, p_msg );
338         return attach_ack( T, branch, ack , len );
339 }
340
341 #endif
342
343
344
345
346 int forward_serial_branch(struct cell* Trans,int branch)
347 {
348         struct sip_msg*  p_msg = Trans->uas.request;
349         struct lump      *a, *b, *b1, *c;
350         unsigned int     len;
351         char             *buf=0, *shbuf=0;
352         str              backup_uri;
353         union sockaddr_union *to;
354         struct socket_info* send_sock;
355
356         backup_uri.s = p_msg->new_uri.s;
357         backup_uri.len = p_msg->new_uri.len;
358
359         /*generates branch param*/
360         if ( add_branch_label( Trans, p_msg , branch )==-1)
361                 goto error;
362         /* remove all the HDR_VIA type lumps - they are in SHM memory!!! */
363         for(b=p_msg->add_rm,b1=0;b;b1=b,b=b->next)
364                 if (b->type==HDR_VIA)
365                 {
366                         for(a=b->before;a;)
367                                 {c=a->before;shm_free_lump(a);a=c;}
368                         for(a=b->after;a;)
369                                 {c=a->after;shm_free_lump(a);a=c;}
370                         if (b1) b1->next = b->next;
371                                 else p_msg->add_rm = b->next;
372                         shm_free_lump(b);
373                 }
374
375         DBG("DEBUG: t_forward_serial_branch: building req for branch"
376                 "%d; uri=|%.*s|.\n", branch, Trans->uac[branch].uri.len,
377                 Trans->uac[branch].uri.s);
378         /* updates the new uri*/
379         p_msg->new_uri.s = Trans->uac[branch].uri.s;
380         p_msg->new_uri.len = Trans->uac[branch].uri.len;
381
382         to=&Trans->uac[branch].request.to;
383         send_sock=get_send_socket(to);
384         if (send_sock==0) {
385                 LOG(L_ERR, "ERROR: t_forward_nonack: can't fwd to af %d "
386                 "no corresponding listening socket\n", to->s.sa_family );
387                 ser_error=E_NO_SOCKET;
388                 goto error;
389         }
390         if ( !(buf = build_req_buf_from_sip_req  ( p_msg, &len, send_sock )))
391                 goto error;
392         shm_free(Trans->uac[branch].uri.s);
393
394         /* allocates a new retrans_buff for the outbound request */
395         shbuf = (char *) shm_malloc( len );
396         if (!shbuf)
397         {
398                 LOG(L_ERR, "ERROR: t_forward_serial_branch: out of shmem buffer\n");
399                 goto error;
400         }
401         Trans->uac[branch].request.buffer = shbuf;
402         Trans->uac[branch].request.buffer_len = len ;
403         memcpy( Trans->uac[branch].request.buffer , buf , len );
404         /* keeps a hooker to uri inside buffer*/
405         Trans->uac[branch].uri.s = Trans->uac[branch].request.buffer +
406                 (p_msg->first_line.u.request.uri.s - p_msg->buf);
407         Trans->uac[branch].uri.len=p_msg->new_uri.len?(p_msg->new_uri.len)
408                 :(p_msg->first_line.u.request.uri.len);
409         Trans->nr_of_outgoings++ ;
410         /* send the request */
411         /* -v6; -jiri Trans->uac[branch].request.to.sin_family = AF_INET; */
412         SEND_BUFFER( &(T->uac[branch].request) );
413
414         pkg_free( buf ) ;
415         buf=NULL;
416
417         DBG("DEBUG: t_forward_serial_branch:starting timers (retrans and FR) %d\n",
418                 get_ticks() );
419         /*sets and starts the FINAL RESPONSE timer */
420         set_timer( hash_table, &(T->uac[branch].request.fr_timer), 
421                         FR_TIMER_LIST ); 
422                         /* p_msg->REQ_METHOD==METHOD_INVITE ? FR_INV_TIMER_LIST : FR_TIMER_LIST ); */
423         /* sets and starts the RETRANS timer */
424         T->uac[branch].request.retr_list = RT_T1_TO_1;
425         set_timer( hash_table, &(T->uac[branch].request.retr_timer), RT_T1_TO_1 );
426
427         p_msg->new_uri.s = backup_uri.s;
428         p_msg->new_uri.len = backup_uri.len;
429
430         for(b=p_msg->add_rm,b1=0;b;b1=b,b=b->next)
431                 if (b->type==HDR_VIA)
432                 {
433                         for(a=b->before;a;)
434                                 {c=a->before;free_lump(a);pkg_free(a);a=c;}
435                         for(a=b->after;a;)
436                                 {c=a->after;free_lump(a);pkg_free(a);a=c;}
437                         if (b1) b1->next = b->next;
438                                 else p_msg->add_rm = b->next;
439                         free_lump(b);pkg_free(b);
440                 }
441
442         return 1;
443
444 error:
445         if (shbuf) shm_free(shbuf);
446         T->uac[branch].request.buffer=NULL;
447         if (buf) pkg_free( buf );
448         p_msg->new_uri.s = backup_uri.s;
449         p_msg->new_uri.len = backup_uri.len;
450         return -1;
451 }
452
453
454