c9eb5694241822da026520f4929ef427d88c304b
[sip-router] / modules / tm / t_funcs.c
1 /*
2  * $Id$
3  *
4  * transaction maintenance functions
5  *
6  * Copyright (C) 2001-2003 Fhg Fokus
7  *
8  * This file is part of ser, a free SIP server.
9  *
10  * ser is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version
14  *
15  * For a license to use the ser software under conditions
16  * other than those described here, or to purchase support for this
17  * software, please contact iptel.org by e-mail at the following addresses:
18  *    info@iptel.org
19  *
20  * ser is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License 
26  * along with this program; if not, write to the Free Software 
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28  */
29
30
31 #include <limits.h>
32 #include "../../dprint.h"
33 #include "../../config.h"
34 #include "../../parser/parser_f.h"
35 #include "../../ut.h"
36 #include "../../hash_func.h"
37 #include "../../dset.h"
38 #include "t_funcs.h"
39 #include "t_fwd.h"
40 #include "t_lookup.h"
41 #include "config.h"
42 #include "t_stats.h"
43
44
45 /* ----------------------------------------------------- */
46
47 int send_pr_buffer( struct retr_buf *rb,
48         void *buf, int len, char *function, int line )
49 {
50         if (buf && len && rb )
51                 return udp_send( rb->send_sock, buf, len, &rb->to) ;
52         else {
53                 LOG(L_CRIT, "ERROR: sending an empty buffer from %s (%d)\n",
54                         function, line );
55                 return -1;
56         }
57 }
58
59 void start_retr( struct retr_buf *rb )
60 {
61         rb->retr_list=RT_T1_TO_1;
62         set_timer( &rb->retr_timer, RT_T1_TO_1 );
63         set_timer( &rb->fr_timer, FR_TIMER_LIST );
64 }
65
66
67
68
69
70 void tm_shutdown()
71 {
72
73         DBG("DEBUG: tm_shutdown : start\n");
74         unlink_timer_lists();
75
76         /* destroy the hash table */
77         DBG("DEBUG: tm_shutdown : empting hash table\n");
78         free_hash_table( );
79         DBG("DEBUG: tm_shutdown: releasing timers\n");
80         free_timer_table();
81         DBG("DEBUG: tm_shutdown : removing semaphores\n");
82         lock_cleanup();
83         free_tm_stats();
84         DBG("DEBUG: tm_shutdown : done\n");
85 }
86
87
88 /*   returns 1 if everything was OK or -1 for error
89 */
90 int t_release_transaction( struct cell *trans )
91 {
92         trans->kr|=REQ_RLSD;
93
94         reset_timer( & trans->uas.response.fr_timer );
95         reset_timer( & trans->uas.response.retr_timer );
96
97         cleanup_uac_timers( trans );
98         
99         put_on_wait( trans );
100         return 1;
101 }
102
103
104 /* ----------------------------HELPER FUNCTIONS-------------------------------- */
105
106
107 /*
108   */
109 void put_on_wait(  struct cell  *Trans  )
110 {
111
112 #ifdef _XWAIT
113         LOCK_WAIT(Trans);
114         if (Trans->on_wait)
115         {
116                 DBG("DEBUG: t_put_on_wait: already on wait\n");
117                 UNLOCK_WAIT(Trans);
118         } else {
119                 Trans->on_wait=1;
120                 UNLOCK_WAIT(Trans);
121         }
122 #endif
123 #ifdef EXTRA_DEBUG
124         DBG("DEBUG: put on WAIT \n");
125 #endif
126
127
128         /* we put the transaction on wait timer; we do it only once
129            in transaction's timelife because putting it multiple-times
130            might result in a second instance of a wait timer to be
131            set after the first one fired; on expiration of the second
132            instance, the transaction would be re-deleted
133
134                         PROCESS1                PROCESS2                TIMER PROCESS
135                 0. 200/INVITE rx;
136                    put_on_wait
137                 1.                                      200/INVITE rx;
138                 2.                                                                      WAIT fires; transaction
139                                                                                         about to be deleted
140                 3.                                      avoid putting
141                                                         on WAIT again
142                 4.                                                                      WAIT timer executed,
143                                                                                         transaction deleted
144         */
145         set_1timer( &Trans->wait_tl, WT_TIMER_LIST );
146 }
147
148
149
150 static int kill_transaction( struct cell *trans )
151 {
152         char err_buffer[128];
153         int sip_err;
154         int reply_ret;
155         int ret;
156
157         /*  we reply statefuly and enter WAIT state since error might
158                 have occured in middle of forking and we do not
159                 want to put the forking burden on upstream client;
160                 howver, it may fail too due to lack of memory */
161
162         ret=err2reason_phrase( ser_error, &sip_err,
163                 err_buffer, sizeof(err_buffer), "TM" );
164         if (ret>0) {
165                 reply_ret=t_reply( trans, trans->uas.request, 
166                         sip_err, err_buffer);
167                 /* t_release_transaction( T ); */
168                 return reply_ret;
169         } else {
170                 LOG(L_ERR, "ERROR: kill_transaction: err2reason failed\n");
171                 return -1;
172         }
173 }
174
175
176
177 int t_relay_to( struct sip_msg  *p_msg , struct proxy_l *proxy,
178         int replicate)
179 {
180         int ret;
181         int new_tran;
182         str *uri;
183         int reply_ret;
184         /* struct hdr_field *hdr; */
185         struct cell *t;
186 #ifdef ACK_FORKING_HACK
187         str ack_uri;
188         str backup_uri;
189 #endif
190
191         ret=0;
192
193         new_tran = t_newtran( p_msg );
194         
195
196         /* parsing error, memory alloc, whatever ... if via is bad
197            and we are forced to reply there, return with 0 (->break),
198            pass error status otherwise
199         */
200         if (new_tran<0) {
201                 ret = (ser_error==E_BAD_VIA && reply_to_via) ? 0 : new_tran;
202                 goto done;
203         }
204         /* if that was a retransmission, return we are happily done */
205         if (new_tran==0) {
206                 ret = 1;
207                 goto done;
208         }
209
210         /* new transaction */
211
212         /* ACKs do not establish a transaction and are fwd-ed statelessly */
213         if ( p_msg->REQ_METHOD==METHOD_ACK) {
214                 DBG( "SER: forwarding ACK  statelessly \n");
215                 if (proxy==0) {
216                         uri=(p_msg->new_uri.s==0 || p_msg->new_uri.len==0) ?
217                                 &p_msg->first_line.u.request.uri :
218                                 &p_msg->new_uri;
219                         proxy=uri2proxy( uri );
220                         if (proxy==0) {
221                                         ret=E_BAD_ADDRESS;
222                                         goto done;
223                         }
224                         ret=forward_request( p_msg , proxy ) ;
225                         free_proxy( proxy );    
226                         free( proxy );
227 #ifdef ACK_FORKING_HACK
228                         backup_uri=p_msg->new_uri;
229                         init_branch_iterator();
230                         while((ack_uri.s=next_branch(&ack_uri.len))) {
231                                 p_msg->new_uri=ack_uri;
232                                 proxy=uri2proxy(ack_uri);
233                                 if (proxy==0) continue;
234                                 forward_request(p_msg, proxy);
235                                 free_proxy( proxy );    
236                                 free( proxy );
237                         }
238                         p_msg->new_uri=backup_uri;
239 #endif
240                 } else {
241                         ret=forward_request( p_msg , proxy ) ;
242 #ifdef ACK_FORKING_HACK
243                         backup_uri=p_msg->new_uri;
244                         init_branch_iterator();
245                         while((ack_uri.s=next_branch(&ack_uri.len))) {
246                                 p_msg->new_uri=ack_uri;
247                                 forward_request(p_msg, proxy);
248                         }
249                         p_msg->new_uri=backup_uri;
250 #endif
251                 }
252                 goto done;
253         }
254
255         /* if replication flag is set, mark the transaction as local
256            so that replies will not be relaied
257         */
258         t=get_t();
259         t->local=replicate;
260
261         /* INVITE processing might take long, partcularly because of DNS
262            look-ups -- let upstream know we're working on it */
263         if (p_msg->REQ_METHOD==METHOD_INVITE )
264         {
265                 DBG( "SER: new INVITE\n");
266                 if (!t_reply( t, p_msg , 100 ,
267                         "trying -- your call is important to us"))
268                                 DBG("SER: ERROR: t_reply (100)\n");
269         } 
270
271         /* now go ahead and forward ... */
272         ret=t_forward_nonack(t, p_msg, proxy);
273         if (ret<=0) {
274                 DBG( "SER:ERROR: t_forward \n");
275                 reply_ret=kill_transaction( t );
276                 if (reply_ret>0) {
277                         /* we have taken care of all -- do nothing in
278                         script */
279                         DBG("ERROR: generation of a stateful reply "
280                                 "on error succeeded\n");
281                         ret=0;
282                 }  else {
283                         DBG("ERROR: generation of a stateful reply "
284                                 "on error failed\n");
285                 }
286         } else {
287                 DBG( "SER: new transaction fwd'ed\n");
288         }
289
290 done:
291         return ret;
292 }