Browse code

- tm migrated to the new timers (tm timers completely re-written). - tm structures re-ordered & cleaned up for better "packing" on 64 bit machines => size reduction (~800 bytes less per transaction on a 64 bit machine) - params: - retr_timer1p1, retr_timer1p2, retr_timer1p3 removed and replaced by retr_timer1 and retr_timer2 - all timer values are now expressed in milliseconds (they were in seconds before). Affected params: fr_timer, fr_inv_timer, wt_timer, delete_timer, retr_timer1, retr_timer2 - retr_timer1 (first retransmission) changed to 500 ms - delete_timer changed to 200 ms - functions: - new t_set_fr(timeout_fr_inv, timeout_fr) -- allows changing the transaction timer from script, even if the transaction was already created (see tm docs for more). - fr_inv_timer/fr_timer can be changed now without any performance penalty - more precise retransmissions timing - overall improved tm speed an memory footprint (e.g. on a 64 bit 2*Xeon 2.8Ghz + HT, optimized ser, NO_DEBUG => ~ 6370 cps new version, ~6000 cps old version + rel_0_9_0 tm inser_timer fix; memory usage @ 6000cps: 490Mb new version, 616Mb old version). - NEWS updated

Andrei Pelinescu-Onciul authored on 10/12/2005 16:04:53
Showing 20 changed files
... ...
@@ -61,7 +61,7 @@ MAIN_NAME=ser
61 61
 VERSION = 0
62 62
 PATCHLEVEL = 10
63 63
 SUBLEVEL =   99
64
-EXTRAVERSION = -dev25-timers
64
+EXTRAVERSION = -dev26-tm-timers
65 65
 
66 66
 RELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
67 67
 OS = $(shell uname -s | sed -e s/SunOS/solaris/ | tr "[A-Z]" "[a-z]")
... ...
@@ -16,8 +16,25 @@ modules:
16 16
                 hashing after an uri (to, from or request uri)
17 17
               - improved uri hashing (password is ignored, port is used only
18 18
                 if != 5060 or 5061)
19
+ - tm        - migrated to the new timers (tm timers completely rewritten)
20
+             - improved speed and less memory usage
21
+             - much more precise reptransmissions timing
22
+             - params: - retr_timer1p1, retr_timer1p2, retr_timer1p3 removed
23
+                         and replaced by retr_timer1 and retr_timer2
24
+                       - all timer values are now expressed in milliseconds
25
+                         (they were in seconds before).
26
+                         Affected params: fr_timer, fr_inv_timer, wt_timer,
27
+                         delete_timer, retr_timer1, retr_timer2
28
+                       - retr_timer1 (first retransmission) changed to 500 ms
29
+                       - delete_timer changed to 200 ms
30
+             - functions:
31
+                       - new t_set_fr(timeout_fr_inv, timeout_fr) -- allows
32
+                         changing the transaction timer from script, even if
33
+                         the transaction was already created (see tm docs for
34
+                         more).
19 35
  
20 36
 core:
37
+ - timer: - improved performance/precision, new api, see doc/timers.txt 
21 38
  - tcp: - improved  performance (io event handling), using OS specific
22 39
            optimizations
23 40
         - 1024 connections limit removed (see tcp_max_connections)
... ...
@@ -34,6 +51,9 @@ core:
34 34
 - default on reply route added: onreply_route {.. } will add a default 
35 35
     onreply route that will be executed for any reply (usefull to catch
36 36
     replies without using tm)
37
+- branch_routes added (tm triggered), only a very limited number of commands
38
+   are available (see tm docs)
39
+- avps directly accessible from script with %avp_name (variable style)
37 40
 new config variables:
38 41
    tos = number  - ip type of service (TOS) value
39 42
    dns_try_ipv6 = yes/no - if yes and a dns lookup fails, it will retry it
... ...
@@ -46,20 +46,20 @@
46 46
 
47 47
 /* FINAL_RESPONSE_TIMER ... tells how long should the transaction engine
48 48
    wait if no final response comes back*/
49
-#define FR_TIME_OUT       30
50
-#define INV_FR_TIME_OUT   120
49
+#define FR_TIME_OUT        30000 /* ms */
50
+#define INV_FR_TIME_OUT   120000 /* ms */
51 51
 
52 52
 /* WAIT timer ... tells how long state should persist in memory after
53 53
    a transaction was finalized*/
54
-#define WT_TIME_OUT       5
54
+#define WT_TIME_OUT       5000 /* ms */
55 55
 
56 56
 /* DELETE timer ... tells how long should the transaction persist in memory
57 57
    after it was removed from the hash table and before it will be deleted */
58
-#define DEL_TIME_OUT      2
58
+#define DEL_TIME_OUT      200 /* ms */
59 59
  
60 60
 /* retransmission timers */
61
-#define RETR_T1           1
62
-#define RETR_T2           4
61
+#define RETR_T1           500 /* ms */
62
+#define RETR_T2          4000 /* ms */
63 63
 
64 64
 /* when first reply is sent, this additional space is allocated so that
65 65
    one does not have to reallocate share memory when the message is
... ...
@@ -366,4 +366,50 @@ t_forward_nonack("1.2.3.4", "5060");
366 366
 	</example>
367 367
     </section>
368 368
 
369
+	<section id="t_set_fr">
370
+	<title>
371
+	    <function>t_set_fr(fr_inv_timeout [, fr_timeout])</function>
372
+	</title>
373
+	<para>
374
+		Sets the fr_inv_timeout and optionally fr_timeout for the current
375
+		transaction. If the transaction is already created (e.g called after
376
+		 <function>t_relay()</function> or in an onreply_route) all the
377
+		 branches will have their final response timeout updated on-the-fly.
378
+		If one of the parameters is 0, it's value won't be changed.
379
+	</para>
380
+	<para>Meaning of the parameters is as follows:</para>
381
+	<itemizedlist>
382
+	    <listitem>
383
+		<para><emphasis>fr_inv_timeout</emphasis> - new final response timeout
384
+			(in milliseconds) for INVITEs. See also 
385
+			<varname>fr_inv_timer</varname>.
386
+		</para>
387
+		<para><emphasis>fr_timeout</emphasis> - new final response timeout
388
+		 	(in milliseconds) for non-INVITE transaction, or INVITEs which 
389
+			haven't received yet a provisional response. See also
390
+			<varname>fr_timer</varname>.
391
+		</para>
392
+	    </listitem>
393
+	</itemizedlist>
394
+	<example>
395
+	    <title><function>t_set_fr</function> usage</title>
396
+	    <programlisting>
397
+...
398
+route { 
399
+	t_set_fr(10000); # set only fr invite timeout to 10s
400
+	t_on_branch("1");
401
+	t_relay(); 
402
+} 
403
+
404
+branch_route[1] {
405
+	# if we are calling the pstn, extend the invite timeout to 50s
406
+	# for all the branches, and set the no-reply-received timeout to 2s
407
+	if (uri=~"sip:[0-9]+"){
408
+		t_set_fr(50000, 2000); 
409
+	}
410
+}
411
+	    </programlisting>
412
+	</example>
413
+	</section>
414
+
369 415
 </section>
... ...
@@ -18,7 +18,7 @@
18 18
 	<title><varname>fr_timer</varname> (integer)</title>
19 19
 	<para>
20 20
 	    Timer which hits if no final reply for a request or ACK for a
21
-	    negative INVITE reply arrives (in seconds).
21
+	    negative INVITE reply arrives (in milliseconds).
22 22
 	</para>
23 23
 	<para>
24 24
 	    Default value is 30 seconds.
... ...
@@ -37,7 +37,7 @@ modparam("tm", "fr_timer", 10)
37 37
 	<title><varname>fr_inv_timer</varname> (integer)</title>
38 38
 	<para>
39 39
 	    Timer which hits if no final reply for an INVITE arrives after a
40
-	    provisional message was received (in seconds).
40
+	    provisional message was received (in milliseconds).
41 41
 	</para>
42 42
 	<para>
43 43
 	    Default value is 120 seconds.
... ...
@@ -81,7 +81,7 @@ modparam("tm", "wt_timer", 10)
81 81
 	    process will be tried to be deleted again.
82 82
 	</para>
83 83
 	<para>
84
-	    Default value is 2 seconds.
84
+	    Default value is 200 milliseconds.
85 85
 	</para>
86 86
 	<example>
87 87
 	    <title>Set <varname>delete_timer</varname> parameter</title>
... ...
@@ -93,55 +93,19 @@ modparam("tm", "delete_timer", 5)
93 93
 	</example>
94 94
     </section>
95 95
     
96
-    <section id="retr_timer1p1">
97
-	<title><varname>retr_timer1p1</varname> (integer)</title>
96
+    <section id="retr_timer1">
97
+	<title><varname>retr_timer1</varname> (integer)</title>
98 98
 	<para>
99
-	    Retransmission period.
99
+	    Initial retransmission period (in milliseconds).
100 100
 	</para>
101 101
 	<para>
102
-	    Default value is 1 second.
102
+	    Default value is 500 milliseconds.
103 103
 	</para>
104 104
 	<example>
105
-	    <title>Set <varname>retr_timer1p1</varname> parameter</title>
105
+	    <title>Set <varname>retr_timer1</varname> parameter</title>
106 106
 	    <programlisting>
107 107
 ...
108
-modparam("tm", "retr_timer1p1", 2)
109
-...
110
-	    </programlisting>
111
-	</example>
112
-    </section>
113
-
114
-    <section id="retr_timer1p2">
115
-	<title><varname>retr_timer1p2</varname> (integer)</title>
116
-	<para>
117
-	    Retransmission period.
118
-	</para>
119
-	<para>
120
-	    Default value is 2 * <varname>retr_timer1p1</varname> second.
121
-	</para>
122
-	<example>
123
-	    <title>Set <varname>retr_timer1p2</varname> parameter</title>
124
-	    <programlisting>
125
-...
126
-modparam("tm", "retr_timer1p2", 4)
127
-...
128
-	    </programlisting>
129
-	</example>
130
-    </section>
131
-
132
-    <section id="retr_timer1p3">
133
-	<title><varname>retr_timer1p3</varname> (integer)</title>
134
-	<para>
135
-	    Retransmission period.
136
-	</para>
137
-	<para>
138
-	    Default value is 4 * <varname>retr_timer1p1</varname> second.
139
-	</para>
140
-	<example>
141
-	    <title>Set <varname>retr_timer1p4</varname> parameter</title>
142
-	    <programlisting>
143
-...
144
-modparam("tm", "retr_timer1p3", 8)
108
+modparam("tm", "retr_timer1", 1000)
145 109
 ...
146 110
 	    </programlisting>
147 111
 	</example>
... ...
@@ -150,16 +114,19 @@ modparam("tm", "retr_timer1p3", 8)
150 150
     <section id="retr_timer2">
151 151
 	<title><varname>retr_timer2</varname> (integer)</title>
152 152
 	<para>
153
-	    Maximum retransmission period.
153
+	    Maximum retransmission period (in milliseconds). The retransmission
154
+		interval starts with <varname>retr_timer1</varname> and increases until
155
+		it reaches this value. After this it stays constant at 
156
+		<varname>retr_timer2</varname>.
154 157
 	</para>
155 158
 	<para>
156
-	    Default value is 4 seconds.
159
+	    Default value is 4000 milliseconds.
157 160
 	</para>
158 161
 	<example>
159 162
 	    <title>Set <varname>retr_timer2</varname> parameter</title>
160 163
 	    <programlisting>
161 164
 ...
162
-modparam("tm", "retr_timer2", 8)
165
+modparam("tm", "retr_timer2", 2000)
163 166
 ...
164 167
 	    </programlisting>
165 168
 	</example>
... ...
@@ -61,6 +61,7 @@
61 61
 #include "t_stats.h"
62 62
 #include "h_table.h"
63 63
 #include "fix_lumps.h" /* free_via_clen_lump */
64
+#include "timer.h"
64 65
 
65 66
 static enum kill_reason kr;
66 67
 
... ...
@@ -213,10 +214,7 @@ static void inline init_branches(struct cell *t)
213 213
 		uac=&t->uac[i];
214 214
 		uac->request.my_T = t;
215 215
 		uac->request.branch = i;
216
-#ifdef EXTRA_DEBUG
217
-		uac->request.fr_timer.tg = TG_FR;
218
-		uac->request.retr_timer.tg = TG_RT;
219
-#endif
216
+		init_rb_timers(&uac->request);
220 217
 		uac->local_cancel=uac->request;
221 218
 	}
222 219
 }
... ...
@@ -239,11 +237,10 @@ struct cell*  build_cell( struct sip_msg* p_msg )
239 239
 	memset( new_cell, 0, sizeof( struct cell ) );
240 240
 
241 241
 	/* UAS */
242
-#ifdef EXTRA_DEBUG
243
-	new_cell->uas.response.retr_timer.tg=TG_RT;
244
-	new_cell->uas.response.fr_timer.tg=TG_FR;
245
-#endif
246 242
 	new_cell->uas.response.my_T=new_cell;
243
+	init_rb_timers(&new_cell->uas.response);
244
+	/* timers */
245
+	init_cell_timers(new_cell);
247 246
 
248 247
 	/* move the current avp list to transaction -bogdan */
249 248
 	old = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER,  &new_cell->user_avps );
... ...
@@ -270,10 +267,6 @@ struct cell*  build_cell( struct sip_msg* p_msg )
270 270
 
271 271
 	new_cell->relayed_reply_branch   = -1;
272 272
 	/* new_cell->T_canceled = T_UNDEFINED; */
273
-#ifdef EXTRA_DEBUG
274
-	new_cell->wait_tl.tg=TG_WT;
275
-	new_cell->dele_tl.tg=TG_DEL;
276
-#endif
277 273
 
278 274
 	init_synonym_id(new_cell);
279 275
 	init_cell_lock(  new_cell );
... ...
@@ -35,6 +35,7 @@
35 35
  * 2004-02-13  t->is_invite, t->local, t->noisy_ctimer replaced
36 36
  *             with flags (bogdan)
37 37
  * 2004-08-23  avp support added - avp list linked in transaction (bogdan)
38
+ * 2005-11-03  updated to the new timer interface (dropped tm timers) (andrei)
38 39
  */
39 40
 
40 41
 #include "defs.h"
... ...
@@ -50,6 +51,7 @@
50 50
 #include "../../types.h"
51 51
 #include "../../md5utils.h"
52 52
 #include "../../usr_avp.h"
53
+#include "../../timer.h"
53 54
 #include "config.h"
54 55
 
55 56
 struct s_table;
... ...
@@ -63,7 +65,7 @@ struct retr_buf;
63 63
 #include "sip_msg.h"
64 64
 #include "t_reply.h"
65 65
 #include "t_hooks.h"
66
-#include "timer.h"
66
+#include "../../timer.h"
67 67
 
68 68
 #define LOCK_HASH(_h) lock_hash((_h))
69 69
 #define UNLOCK_HASH(_h) unlock_hash((_h))
... ...
@@ -98,25 +100,28 @@ void unlock_hash(int i);
98 98
 enum kill_reason { REQ_FWDED=1, REQ_RPLD=2, REQ_RLSD=4, REQ_EXIST=8 };
99 99
 
100 100
 
101
+/* #define F_RB_T_ACTIVE		0x01  (obsolete) fr or retr active */
102
+#define F_RB_T2				0x02
103
+#define F_RB_RETR_DISABLED	0x04 /* retransmission disabled */
104
+#define F_RB_FR_INV	0x08 /* timer switched to FR_INV */
105
+
106
+
101 107
 typedef struct retr_buf
102 108
 {
103
-	int activ_type;
109
+	short activ_type;
104 110
 	/* set to status code if the buffer is a reply,
105 111
 	0 if request or -1 if local CANCEL */
106
-
112
+	volatile unsigned char flags; /* DISABLED, T2 */
113
+	volatile unsigned char t_active; /* timer active */
114
+	unsigned short branch; /* no more then 65k branches :-) */
115
+	short   buffer_len;
107 116
 	char *buffer;
108
-	int   buffer_len;
109
-	
110
-	struct dest_info dst;
111
-
112
-	/* a message can be linked just to retransmission and FR list */
113
-	struct timer_link retr_timer;
114
-	struct timer_link fr_timer;
115
-	enum lists retr_list;
116
-
117 117
 	/*the cell that contains this retrans_buff*/
118 118
 	struct cell* my_T;
119
-	unsigned int branch;
119
+	struct timer_ln timer;
120
+	struct dest_info dst;
121
+	ticks_t retr_expire;
122
+	ticks_t fr_expire; /* ticks value after which fr. will fire */
120 123
 }retr_buf_type;
121 124
 
122 125
 
... ...
@@ -128,11 +133,11 @@ typedef struct ua_server
128 128
 	struct sip_msg   *request;
129 129
 	char             *end_request;
130 130
 	struct retr_buf  response;
131
-	unsigned int     status;
132 131
 	/* keep to-tags for local 200 replies for INVITE -- 
133 132
 	 * we need them for dialog-wise matching of ACKs;
134 133
 	 * the pointer shows to shmem-ed reply */
135 134
 	str				 local_totag;
135
+	unsigned int     status;
136 136
 }ua_server_type;
137 137
 
138 138
 
... ...
@@ -160,9 +165,9 @@ typedef struct ua_client
160 160
 
161 161
 
162 162
 struct totag_elem {
163
+	struct totag_elem *next;
163 164
 	str tag;
164 165
 	short acked;
165
-	struct totag_elem *next;
166 166
 };
167 167
 
168 168
 
... ...
@@ -176,7 +181,8 @@ struct totag_elem {
176 176
    dropping when C timer hits */
177 177
 #define T_NOISY_CTIMER_FLAG  (1<<2)
178 178
 
179
-
179
+#define T_IN_AGONY (1<<3) /* set if waiting to die (delete timer)
180
+                             TODO: replace it with del on unref */
180 181
 
181 182
 /* transaction context */
182 183
 
... ...
@@ -190,7 +196,9 @@ typedef struct cell
190 190
 	/* sequence number within hash collision slot */
191 191
 	unsigned int  label;
192 192
 	/* different information about the transaction */
193
-	unsigned int flags;
193
+	unsigned short flags;
194
+	/* number of forks */
195
+	short nr_of_outgoings;
194 196
 
195 197
 	/* how many processes are currently processing this transaction ;
196 198
 	   note that only processes working on a request/reply belonging
... ...
@@ -218,44 +226,40 @@ typedef struct cell
218 218
 	struct tmcb_head_list tmcb_hl;
219 219
 
220 220
 	/* bindings to wait and delete timer */
221
-	struct timer_link wait_tl;
222
-	struct timer_link dele_tl;
221
+	struct timer_ln wait_timer; /* used also for delete */
223 222
 
224
-	/* number of forks */
225
-	int nr_of_outgoings;
226
-	/* nr of replied branch; 0..MAX_BRANCHES=branch value,
227
-	 * -1 no reply, -2 local reply */
228
-	int relayed_reply_branch;
229 223
 	/* UA Server */
230 224
 	struct ua_server  uas;
231 225
 	/* UA Clients */
232 226
 	struct ua_client  uac[ MAX_BRANCHES ];
233
-
227
+	
228
+	/* to-tags of 200/INVITEs which were received from downstream and 
229
+	 * forwarded or passed to UAC; note that there can be arbitrarily 
230
+	 * many due to downstream forking; */
231
+	struct totag_elem *fwded_totags;
232
+	/* list with user avp */
233
+	struct usr_avp *user_avps;
234
+	
234 235
 	/* protection against concurrent reply processing */
235 236
 	ser_lock_t   reply_mutex;
237
+	
238
+	ticks_t fr_timeout;     /* final response interval for retr_bufs */
239
+	ticks_t fr_inv_timeout; /* final inv. response interval for retr_bufs */
240
+
241
+	/* nr of replied branch; 0..MAX_BRANCHES=branch value,
242
+	 * -1 no reply, -2 local reply */
243
+	short relayed_reply_branch;
236 244
 
237 245
 	/* the route to take if no final positive reply arrived */
238
-	unsigned int on_negative;
246
+	unsigned short on_negative;
239 247
 	/* the onreply_route to be processed if registered to do so */
240
-	unsigned int on_reply;
241
-	     /* The route to take for each downstream branch separately */
242
-	unsigned int on_branch;
248
+	unsigned short on_reply;
249
+	 /* The route to take for each downstream branch separately */
250
+	unsigned short on_branch;
243 251
 
244
-	/* MD5checksum  (meaningful only if syn_branch=0 */
252
+	/* MD5checksum  (meaningful only if syn_branch=0) */
245 253
 	char md5[MD5_LEN];
246 254
 
247
-#ifdef	EXTRA_DEBUG
248
-	/* scheduled for deletion ? */
249
-	short damocles;
250
-#endif
251
-
252
-	/* to-tags of 200/INVITEs which were received from downstream and 
253
-	 * forwarded or passed to UAC; note that there can be arbitrarily 
254
-	 * many due to downstream forking; */
255
-	struct totag_elem *fwded_totags;
256
-
257
-	/* list with user avp */
258
-	struct usr_avp *user_avps;
259 255
 }cell_type;
260 256
 
261 257
 
... ...
@@ -294,10 +294,3 @@ int release_timerlist_lock( struct timer *timerlist )
294 294
 	/* the same as above */
295 295
 	return 0;
296 296
 }
297
-
298
-int init_timerlist_lock( enum lists timerlist_id)
299
-{
300
-	get_timertable()->timers[timerlist_id].mutex=
301
-		&(timer_group_lock[ timer_group[timerlist_id] ]);
302
-	return 0;
303
-}
... ...
@@ -68,7 +68,6 @@ enum timer_groups {
68 68
 
69 69
 
70 70
 #include "h_table.h"
71
-#include "timer.h" 
72 71
 
73 72
 /* Uni*x permissions for IPC */
74 73
 #define IPC_PERMISSIONS 0666
... ...
@@ -133,7 +132,6 @@ static inline void _unlock( ser_lock_t* s )
133 133
 #endif
134 134
 }
135 135
 
136
-int init_timerlist_lock(  enum lists timerlist_id);
137 136
 
138 137
 
139 138
 #endif
... ...
@@ -108,22 +108,21 @@ void cancel_branch( struct cell *t, int branch )
108 108
 		LOG(L_ERR, "ERROR: attempt to build a CANCEL failed\n");
109 109
 		return;
110 110
 	}
111
-
112
-	     /* install cancel now */
111
+	/* install cancel now */
113 112
 	crb->buffer = cancel;
114 113
 	crb->buffer_len = len;
115 114
 	crb->dst = irb->dst;
116 115
 	crb->branch = branch;
117
-
118 116
 	/* label it as cancel so that FR timer can better now how to
119 117
 	   deal with it */
120 118
 	crb->activ_type = TYPE_LOCAL_CANCEL;
121 119
 
122 120
 	DBG("DEBUG: cancel_branch: sending cancel...\n");
123 121
 	SEND_BUFFER( crb );
124
-	
125
-	     /*sets and starts the FINAL RESPONSE timer */
126
-	start_retr( crb );
122
+	/*sets and starts the FINAL RESPONSE timer */
123
+	if (start_retr( crb )!=0)
124
+		LOG(L_CRIT, "BUG: cancel_branch: failed to start retransmission"
125
+					" for %p\n", crb);
127 126
 }
128 127
 
129 128
 
... ...
@@ -96,13 +96,10 @@ void tm_shutdown()
96 96
 {
97 97
 
98 98
 	DBG("DEBUG: tm_shutdown : start\n");
99
-	unlink_timer_lists();
100 99
 
101 100
 	/* destroy the hash table */
102 101
 	DBG("DEBUG: tm_shutdown : emptying hash table\n");
103 102
 	free_hash_table( );
104
-	DBG("DEBUG: tm_shutdown : releasing timers\n");
105
-	free_timer_table();
106 103
 	DBG("DEBUG: tm_shutdown : removing semaphores\n");
107 104
 	lock_cleanup();
108 105
 	DBG("DEBUG: tm_shutdown : destroying tmcb lists\n");
... ...
@@ -118,9 +115,7 @@ int t_release_transaction( struct cell *trans )
118 118
 {
119 119
 	set_kr(REQ_RLSD);
120 120
 
121
-	reset_timer( & trans->uas.response.fr_timer );
122
-	reset_timer( & trans->uas.response.retr_timer );
123
-
121
+	stop_rb_timers(&trans->uas.response);
124 122
 	cleanup_uac_timers( trans );
125 123
 	
126 124
 	put_on_wait( trans );
... ...
@@ -158,7 +153,12 @@ void put_on_wait(  struct cell  *Trans  )
158 158
 		4.									WAIT timer executed,
159 159
 											transaction deleted
160 160
 	*/
161
-	set_1timer( &Trans->wait_tl, WT_TIMER_LIST, 0 );
161
+	if (timer_add(&Trans->wait_timer, wait_timeout)==0){
162
+		/* sucess */
163
+		t_stats_wait();
164
+	}else{
165
+		DBG("tm: put_on_wait: transaction %p already on wait\n", Trans);
166
+	}
162 167
 }
163 168
 
164 169
 
... ...
@@ -32,6 +32,8 @@
32 32
   *  2003-03-13  now send_pr_buffer will be called w/ function/line info
33 33
   *               only when compiling w/ -DEXTRA_DEBUG (andrei)
34 34
   *  2003-03-31  200 for INVITE/UAS resent even for UDP (jiri) 
35
+  *  2005-11-09  added stop_rb_timers, updated to the new timer interface 
36
+  *               (andrei)
35 37
   */
36 38
 
37 39
 
... ...
@@ -124,37 +126,26 @@ int fr_avp2timer(unsigned int* timer);
124 124
 int fr_inv_avp2timer(unsigned int* timer);
125 125
 
126 126
 
127
+#ifdef TIMER_DEBUG
128
+#define start_retr(rb) \
129
+	_set_fr_retr((rb), \
130
+				((rb)->dst.proto==PROTO_UDP)?rt_t1_timeout:(ticks_t)(-1), \
131
+				__FILE__, __FUNCTION__, __LINE__)
127 132
 
128
-static void inline _set_fr_retr( struct retr_buf *rb, int retr )
129
-{
130
-	unsigned int timer;
133
+#define force_retr(rb) \
134
+	_set_fr_retr((rb), rt_t1_timeout, __FILE__, __FUNCTION__, __LINE__)
131 135
 
132
-	if (retr) {
133
-		rb->retr_list=RT_T1_TO_1;
134
-		set_timer( &rb->retr_timer, RT_T1_TO_1, 0 );
135
-	}
136
+#else
137
+#define start_retr(rb) \
138
+	_set_fr_retr((rb), \
139
+				((rb)->dst.proto==PROTO_UDP)?rt_t1_timeout:(ticks_t)(-1))
140
+
141
+#define force_retr(rb) \
142
+	_set_fr_retr((rb), rt_t1_timeout)
136 143
 
137
-	if (!fr_avp2timer(&timer)) {
138
-		DBG("_set_fr_retr: FR_TIMER = %d\n", timer);
139
-		set_timer(&rb->fr_timer, FR_TIMER_LIST, &timer);
140
-		     /* Automatically enable noisy_ctimer for the
141
-		      * transaction
142
-		      */
143
-		rb->my_T->flags |= T_NOISY_CTIMER_FLAG;
144
-	} else {
145
-		set_timer(&rb->fr_timer, FR_TIMER_LIST, 0);
146
-	}
147
-}
144
+#endif
148 145
 
149
-static void inline start_retr(struct retr_buf *rb)
150
-{
151
-	_set_fr_retr(rb, rb->dst.proto==PROTO_UDP);
152
-}
153 146
 
154
-static void inline force_retr(struct retr_buf *rb)
155
-{
156
-	_set_fr_retr(rb, 1);
157
-}
158 147
 
159 148
 
160 149
 void tm_shutdown();
... ...
@@ -177,7 +168,6 @@ int get_ip_and_port_from_uri( str* uri , unsigned int *param_ip,
177 177
 
178 178
 void put_on_wait(  struct cell  *Trans  );
179 179
 
180
-void cleanup_localcancel_timers( struct cell *t );
181 180
 
182 181
 int t_relay_to( struct sip_msg  *p_msg ,
183 182
 	struct proxy_l *proxy, int proto, int replicate ) ;
... ...
@@ -202,7 +202,9 @@ int add_blind_uac( /*struct cell *t*/ )
202 202
 	/* start FR timer -- protocol set by default to PROTO_NONE,
203 203
        which means retransmission timer will not be started
204 204
     */
205
-	start_retr(&t->uac[branch].request);
205
+	if (start_retr(&t->uac[branch].request)!=0)
206
+		LOG(L_CRIT, "BUG: add_blind_uac: start retr failed for %p\n",
207
+				&t->uac[branch].request);
206 208
 	/* we are on a timer -- don't need to put on wait on script
207 209
 	   clean-up	
208 210
 	*/
... ...
@@ -263,7 +265,7 @@ int add_uac( struct cell *t, struct sip_msg *request, str *uri, str* next_hop,
263 263
 	}
264 264
 
265 265
 	hostent2su( &to, &proxy->host, proxy->addr_idx, 
266
-		proxy->port ? proxy->port:SIP_PORT);
266
+		proxy->port ? proxy->port:((proto==PROTO_TLS)?SIPS_PORT:SIP_PORT));
267 267
 
268 268
 	send_sock=get_send_socket( request, &to , proto);
269 269
 	if (send_sock==0) {
... ...
@@ -396,18 +398,20 @@ void e2e_cancel( struct sip_msg *cancel_msg,
396 396
 			if (SEND_BUFFER(&t_cancel->uac[i].request) == -1) {
397 397
 				LOG(L_ERR, "ERROR: e2e_cancel: send failed\n");
398 398
 			}
399
-			start_retr(&t_cancel->uac[i].request);
399
+			if (start_retr( &t_cancel->uac[i].request )!=0)
400
+				LOG(L_CRIT, "BUG: e2e_cancel: failed to start retr. for %p\n",
401
+							&t_cancel->uac[i].request);
400 402
 		} else {
401 403
 			if (t_invite->uac[i].last_received < 100) {
402
-				     /* No provisional response received, stop
403
-				      * retransmission timers
404
-				      */
405
-				reset_timer(&t_invite->uac[i].request.retr_timer);
406
-				reset_timer(&t_invite->uac[i].request.fr_timer);
407
-
408
-				     /* Generate faked reply */
404
+				/* No provisional response received, stop
405
+				 * retransmission timers */
406
+				stop_rb_retr(&t_invite->uac[i].request);
407
+				/* no need to stop fr, it will be stoped by relay_reply
408
+				 * put_on_wait -- andrei */
409
+				/* Generate faked reply */
409 410
 				LOCK_REPLIES(t_invite);
410
-				if (relay_reply(t_invite, FAKED_REPLY, i, 487, &tmp_bm) == RPS_ERROR) {
411
+				if (relay_reply(t_invite, FAKED_REPLY, i, 487, &tmp_bm) == 
412
+						RPS_ERROR) {
411 413
 					lowest_error = -1;
412 414
 				}
413 415
 			}
... ...
@@ -553,7 +557,9 @@ int t_forward_nonack( struct cell *t, struct sip_msg* p_msg ,
553 553
 			} else {
554 554
 				success_branch++;
555 555
 			}
556
-			start_retr( &t->uac[i].request );
556
+			if (start_retr( &t->uac[i].request )!=0)
557
+				LOG(L_CRIT, "BUG: t_forward_non_ack: "
558
+						"failed to start retr. for %p\n", &t->uac[i].request);
557 559
 		}
558 560
 	}
559 561
 	if (success_branch<=0) {
... ...
@@ -79,6 +79,7 @@
79 79
  * 2004-10-10: use of mhomed disabled for replies (jiri)
80 80
  * 2005-02-01: use the incoming request interface for sending the replies
81 81
  *             - changes in init_rb() (bogdan)
82
+ *  2005-12-09  added t_set_fr()  (andrei)
82 83
  */
83 84
 
84 85
 #include "defs.h"
... ...
@@ -91,6 +92,7 @@
91 91
 #include "../../parser/parse_from.h"
92 92
 #include "../../ut.h"
93 93
 #include "../../timer.h"
94
+#include "../../timer_ticks.h"
94 95
 #include "../../hash_func.h"
95 96
 #include "../../globals.h"
96 97
 #include "../../forward.h"
... ...
@@ -920,9 +922,9 @@ int t_check( struct sip_msg* p_msg , int *param_branch )
920 920
 
921 921
 		}
922 922
 #ifdef EXTRA_DEBUG
923
-		if ( T && T!=T_UNDEFINED && T->damocles) {
923
+		if ( T && T!=T_UNDEFINED && T->flags & (T_IN_AGONY)) {
924 924
 			LOG( L_ERR, "ERROR: transaction %p scheduled for deletion "
925
-				"and called from t_check\n", T);
925
+				"and called from t_check (flags=%x)\n", T, T->flags);
926 926
 			abort();
927 927
 		}
928 928
 #endif
... ...
@@ -945,6 +947,7 @@ int init_rb( struct retr_buf *rb, struct sip_msg *msg)
945 945
 	int proto;
946 946
 	int backup_mhomed;
947 947
 
948
+	/* rb. timers are init. init_t()/new_cell() */
948 949
 	via=msg->via1;
949 950
 	if (!reply_to_via) {
950 951
 		update_sock_struct_from_ip( &rb->dst.to, msg );
... ...
@@ -983,6 +986,7 @@ int init_rb( struct retr_buf *rb, struct sip_msg *msg)
983 983
 static inline void init_new_t(struct cell *new_cell, struct sip_msg *p_msg)
984 984
 {
985 985
 	struct sip_msg *shm_msg;
986
+	unsigned int timeout; /* avp timeout gets stored here (in s) */
986 987
 
987 988
 	shm_msg=new_cell->uas.request;
988 989
 	new_cell->from.s=shm_msg->from->name.s;
... ...
@@ -1000,6 +1004,27 @@ static inline void init_new_t(struct cell *new_cell, struct sip_msg *p_msg)
1000 1000
 	if (p_msg->REQ_METHOD==METHOD_INVITE) new_cell->flags |= T_IS_INVITE_FLAG;
1001 1001
 	new_cell->on_negative=get_on_negative();
1002 1002
 	new_cell->on_reply=get_on_reply();
1003
+	new_cell->fr_timeout=(ticks_t)get_msgid_val(user_fr_timeout,
1004
+												p_msg->id, int);
1005
+	new_cell->fr_inv_timeout=(ticks_t)get_msgid_val(user_fr_inv_timeout,
1006
+												p_msg->id, int);
1007
+	if (new_cell->fr_timeout==0){
1008
+		if (!fr_avp2timer(&timeout)) {
1009
+			DBG("init_new_t: FR__TIMER = %d s\n", timeout);
1010
+			new_cell->fr_timeout=S_TO_TICKS((ticks_t)timeout);
1011
+		}else{
1012
+			new_cell->fr_timeout=fr_timeout;
1013
+		}
1014
+	}
1015
+	if (new_cell->fr_inv_timeout==0){
1016
+		if (!fr_inv_avp2timer(&timeout)) {
1017
+			DBG("init_new_t: FR_INV_TIMER = %d s\n", timeout);
1018
+			new_cell->fr_inv_timeout=S_TO_TICKS((ticks_t)timeout);
1019
+			new_cell->flags |= T_NOISY_CTIMER_FLAG;
1020
+		}else{
1021
+			new_cell->fr_inv_timeout=fr_inv_timeout;
1022
+		}
1023
+	}
1003 1024
 	new_cell->on_branch=get_on_branch();
1004 1025
 }
1005 1026
 
... ...
@@ -1322,3 +1347,36 @@ int t_lookup_callid(struct cell ** trans, str callid, str cseq) {
1322 1322
 	return -1;
1323 1323
 }
1324 1324
 
1325
+
1326
+
1327
+/* params: fr_inv & fr value in ms, 0 means "do not touch"
1328
+ * ret: 1 on success, -1 on error (script safe)*/
1329
+int t_set_fr(struct sip_msg* msg, unsigned int fr_inv_to, unsigned int fr_to)
1330
+{
1331
+	struct cell *t;
1332
+	ticks_t fr_inv, fr;
1333
+	
1334
+	
1335
+	fr_inv=MS_TO_TICKS((ticks_t)fr_inv_to);
1336
+	if ((fr_inv==0) && (fr_inv_to!=0)){
1337
+		ERR("t_set_fr_inv: fr_inv_timeout too small (%d)\n", fr_inv_to);
1338
+		return -1;
1339
+	}
1340
+	fr=MS_TO_TICKS((ticks_t)fr_to);
1341
+	if ((fr==0) && (fr_to!=0)){
1342
+		ERR("t_set_fr_inv: fr_timeout too small (%d)\n", fr_to);
1343
+		return -1;
1344
+	}
1345
+	
1346
+	t=get_t();
1347
+	/* in MODE_REPLY and MODE_ONFAILURE T will be set to current transaction;
1348
+	 * in MODE_REQUEST T will be set only if the transaction was already
1349
+	 * created; if not -> use the static variable */
1350
+	if (!t || t==T_UNDEFINED ){
1351
+		set_msgid_val(user_fr_inv_timeout, msg->id, int, (int)fr_inv);
1352
+		set_msgid_val(user_fr_timeout, msg->id, int, (int)fr);
1353
+	}else{
1354
+		change_fr(t, fr_inv, fr); /* change running uac timers */
1355
+	}
1356
+	return 1;
1357
+}
... ...
@@ -30,6 +30,7 @@
30 30
  *  2003-02-24  s/T_NULL/T_NULL_CELL/ to avoid redefinition conflict w/
31 31
  *               nameser_compat.h (andrei)
32 32
  *  2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
33
+ *  2005-12-09  added t_set_fr()  (andrei)
33 34
  */
34 35
 
35 36
 
... ...
@@ -94,5 +95,7 @@ int t_lookup_ident(struct cell** trans, unsigned int hash_index, unsigned int la
94 94
 /* lookup a transaction by callid and cseq */
95 95
 int t_lookup_callid(struct cell** trans, str callid, str cseq);
96 96
 
97
+int t_set_fr(struct sip_msg* msg, unsigned int fr_inv_to, unsigned int fr_to );
98
+
97 99
 #endif
98 100
 
... ...
@@ -66,6 +66,7 @@
66 66
  *              the request (bogdan)
67 67
  *  2005-09-01  reverted to the old way of checking response.dst.send_sock
68 68
  *               in t_retransmit_reply & reply_light (andrei)
69
+ *  2005-11-09  updated to the new timers interface (andrei)
69 70
  */
70 71
 
71 72
 
... ...
@@ -940,7 +941,9 @@ void set_final_timer( /* struct s_table *h_table, */ struct cell *t )
940 940
 	if ( !is_local(t) && t->uas.request->REQ_METHOD==METHOD_INVITE ) {
941 941
 		/* crank timers for negative replies */
942 942
 		if (t->uas.status>=300) {
943
-			start_retr(&t->uas.response);
943
+			if (start_retr(&t->uas.response)!=0)
944
+				LOG(L_CRIT, "BUG: set_final_timer: start retr failed for %p\n",
945
+						&t->uas.response);
944 946
 			return;
945 947
 		}
946 948
 		/* local UAS retransmits too */
... ...
@@ -949,7 +952,9 @@ void set_final_timer( /* struct s_table *h_table, */ struct cell *t )
949 949
 			   even if TCP used, UDP could be used upstream and
950 950
 			   loose the 200, which is not retransmitted by proxies
951 951
 			*/
952
-			force_retr( &t->uas.response );
952
+			if (force_retr( &t->uas.response )!=0)
953
+				LOG(L_CRIT, "BUG: set_final_timer: force retr failed for %p\n",
954
+						&t->uas.response);
953 955
 			return;
954 956
 		}
955 957
 	}
... ...
@@ -961,9 +966,8 @@ void cleanup_uac_timers( struct cell *t )
961 961
 	int i;
962 962
 
963 963
 	/* reset FR/retransmission timers */
964
-	for (i=0; i<t->nr_of_outgoings; i++ )  {
965
-		reset_timer( &t->uac[i].request.retr_timer );
966
-		reset_timer( &t->uac[i].request.fr_timer );
964
+	for (i=0; i<t->nr_of_outgoings; i++ ){
965
+		stop_rb_timers(&t->uac[i].request);
967 966
 	}
968 967
 	DBG("DEBUG: cleanup_uac_timers: RETR/FR timers reset\n");
969 968
 }
... ...
@@ -1268,7 +1272,6 @@ int reply_received( struct sip_msg  *p_msg )
1268 1268
 	struct cell *t;
1269 1269
 	str next_hop;
1270 1270
 	avp_list_t* backup_list;
1271
-	unsigned int timer;
1272 1271
 
1273 1272
 	/* make sure we know the associated transaction ... */
1274 1273
 	if (t_check( p_msg  , &branch )==-1)
... ...
@@ -1293,40 +1296,46 @@ int reply_received( struct sip_msg  *p_msg )
1293 1293
 		/* .. which is not e2e ? ... */
1294 1294
 		&& is_invite(t) ) {
1295 1295
 			/* ... then just stop timers */
1296
-			reset_timer( &uac->local_cancel.retr_timer);
1297 1296
 			if ( msg_status >= 200 )
1298
-				reset_timer( &uac->local_cancel.fr_timer);
1297
+				stop_rb_timers(&uac->local_cancel); /* stop retr & fr */
1298
+			else
1299
+				stop_rb_retr(&uac->local_cancel);  /* stop only retr */
1299 1300
 			DBG("DEBUG: reply to local CANCEL processed\n");
1300 1301
 			goto done;
1301 1302
 	}
1302 1303
 
1303 1304
 
1304
-	/* *** stop timers *** */
1305
-	/* stop retransmission */
1306
-	reset_timer( &uac->request.retr_timer);
1307
-	/* stop final response timer only if I got a final response */
1308
-	if ( msg_status >= 200 )
1309
-		reset_timer( &uac->request.fr_timer);
1305
+	if ( msg_status >= 200 ){
1306
+		/* stop final response timer  & retr. only if I got a final response */
1307
+		stop_rb_timers(&uac->request); 
1310 1308
 		/* acknowledge negative INVITE replies (do it before detailed
1311 1309
 		 * on_reply processing, which may take very long, like if it
1312 1310
 		 * is attempted to establish a TCP connection to a fail-over dst */
1313
-
1314
-	if (is_invite(t)) {
1315
-		if (msg_status >= 300) {
1316
-			ack = build_ack(p_msg, t, branch, &ack_len);
1317
-			if (ack) {
1318
-				SEND_PR_BUFFER(&uac->request, ack, ack_len);
1319
-				shm_free(ack);
1320
-			}
1321
-		} else if (is_local(t) && msg_status >= 200) {
1322
-			ack = build_local_ack(p_msg, t, branch, &ack_len, &next_hop);
1323
-			if (ack) {
1324
-				if (send_local_ack(p_msg, &next_hop, ack, ack_len) < 0) {
1325
-					LOG(L_ERR, "Error while sending local ACK\n");
1311
+		if (is_invite(t)) {
1312
+			if (msg_status >= 300) {
1313
+				ack = build_ack(p_msg, t, branch, &ack_len);
1314
+				if (ack) {
1315
+					SEND_PR_BUFFER(&uac->request, ack, ack_len);
1316
+					shm_free(ack);
1317
+				}
1318
+			} else if (is_local(t) /*&& msg_status >= 200*/) {
1319
+				ack = build_local_ack(p_msg, t, branch, &ack_len, &next_hop);
1320
+				if (ack) {
1321
+					if (send_local_ack(p_msg, &next_hop, ack, ack_len) < 0) {
1322
+						LOG(L_ERR, "Error while sending local ACK\n");
1323
+					}
1324
+					shm_free(ack);
1326 1325
 				}
1327
-				shm_free(ack);
1328 1326
 			}
1329 1327
 		}
1328
+	}else{
1329
+		if (is_invite(t)){
1330
+			/* stop only retr. (and not fr) */
1331
+			stop_rb_retr(&uac->request);
1332
+		}else{
1333
+			/* non-invite: increase retransmissions interval (slow now) */
1334
+			switch_rb_retr_to_t2(&uac->request);
1335
+		}
1330 1336
 	}
1331 1337
 	/* processing of on_reply block */
1332 1338
 	if (t->on_reply) {
... ...
@@ -1351,7 +1360,8 @@ int reply_received( struct sip_msg  *p_msg )
1351 1351
 			      */
1352 1352
 			cleanup_uac_timers( t );
1353 1353
 			if (is_invite(t)) cancel_uacs( t, cancel_bitmap );
1354
-			     /* FR for negative INVITES, WAIT anything else */
1354
+			/* There is no need to call set_final_timer because we know
1355
+>--->--->--- * that the transaction is local */
1355 1356
 			put_on_wait(t);
1356 1357
 		}
1357 1358
 	} else {
... ...
@@ -1363,8 +1373,11 @@ int reply_received( struct sip_msg  *p_msg )
1363 1363
 			     */
1364 1364
 			cleanup_uac_timers( t );
1365 1365
 			if (is_invite(t)) cancel_uacs( t, cancel_bitmap );
1366
-			     /* FR for negative INVITES, WAIT anything else */
1367
-			     /* set_final_timer(t) */
1366
+			/* FR for negative INVITES, WAIT anything else */
1367
+			/* Call to set_final_timer is embedded in relay_reply to avoid
1368
+			 * race conditions when reply is sent out and an ACK to stop
1369
+			 * retransmissions comes before retransmission timer is set.*/
1370
+			/* set_final_timer(t) */
1368 1371
 		}
1369 1372
 
1370 1373
 	}
... ...
@@ -1378,25 +1391,11 @@ int reply_received( struct sip_msg  *p_msg )
1378 1378
 					((msg_status>=180) || (last_uac_status==0)) )
1379 1379
 			) ) { /* provisional now */
1380 1380
 		if (is_invite(t)) {
1381
-			/* invite: change FR to longer FR_INV, do not
1382
-			   attempt to restart retransmission any more
1383
-			*/
1384
-
1385
-			backup_list = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER,  &t->user_avps );
1386
-			if (!fr_inv_avp2timer(&timer)) {
1387
-				DBG("reply_received: FR_INV_TIMER = %d\n", timer);
1388
-				set_timer( & uac->request.fr_timer,
1389
-					   FR_INV_TIMER_LIST, &timer );
1390
-				t->flags |= T_NOISY_CTIMER_FLAG;
1391
-			} else {
1392
-				set_timer( & uac->request.fr_timer,
1393
-					   FR_INV_TIMER_LIST, 0 );
1394
-			}
1381
+			backup_list = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, 
1382
+										&t->user_avps );
1383
+			restart_rb_fr(& uac->request, t->fr_inv_timeout);
1384
+			uac->request.flags|=F_RB_FR_INV; /* mark fr_inv */
1395 1385
 			set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER,  backup_list );
1396
-		} else {
1397
-			     /* non-invite: restart retransmissions (slow now) */
1398
-			uac->request.retr_list=RT_T2;
1399
-			set_timer(  & uac->request.retr_timer, RT_T2, 0 );
1400 1386
 		}
1401 1387
 	} /* provisional replies */
1402 1388
 
... ...
@@ -98,6 +98,7 @@
98 98
  *  2003-06-27  timers are not unlinked if timerlist is 0 (andrei)
99 99
  *  2004-02-13  t->is_invite, t->local, t->noisy_ctimer replaced;
100 100
  *              timer_link.payload removed (bogdan)
101
+ *  2005-10-03  almost completely rewritten to use the new timers (andrei)
101 102
  */
102 103
 
103 104
 #include "defs.h"
... ...
@@ -116,125 +117,108 @@
116 116
 #include "../../config.h"
117 117
 #include "../../parser/parser_f.h"
118 118
 #include "../../ut.h"
119
+#include "../../timer_ticks.h"
119 120
 #include "t_funcs.h"
120 121
 #include "t_reply.h"
121 122
 #include "t_cancel.h"
122 123
 
123 124
 
124
-static struct timer_table *timertable=0;
125
-static struct timer detached_timer; /* just to have a value to compare with*/
126 125
 
127
-#define DETACHED_LIST (&detached_timer)
126
+int noisy_ctimer=0;
128 127
 
129
-#define is_in_timer_list2(_tl) ( (_tl)->timer_list &&  \
130
-									((_tl)->timer_list!=DETACHED_LIST) )
128
+struct msgid_var user_fr_timeout;
129
+struct msgid_var user_fr_inv_timeout;
131 130
 
132
-int noisy_ctimer=0;
131
+/* default values of timeouts for all the timer list */
133 132
 
133
+ticks_t fr_timeout		=	FR_TIME_OUT;
134
+ticks_t fr_inv_timeout	=	INV_FR_TIME_OUT;
135
+ticks_t wait_timeout	=	WT_TIME_OUT;
136
+ticks_t delete_timeout	=	DEL_TIME_OUT;
137
+ticks_t rt_t1_timeout	=	RETR_T1;
138
+ticks_t rt_t2_timeout	=	RETR_T2;
134 139
 
135
-int timer_group[NR_OF_TIMER_LISTS] = 
140
+/* fix timer values to ticks */
141
+int tm_init_timers()
136 142
 {
137
-	TG_FR, TG_FR,
138
-	TG_WT,
139
-	TG_DEL,
140
-	TG_RT, TG_RT, TG_RT, TG_RT
141
-};
142
-
143
-/* default values of timeouts for all the timer list
144
-   (see timer.h for enumeration of timer lists)
145
-*/
146
-unsigned int timer_id2timeout[NR_OF_TIMER_LISTS] = {
147
-	FR_TIME_OUT, 		/* FR_TIMER_LIST */
148
-	INV_FR_TIME_OUT, 	/* FR_INV_TIMER_LIST */
149
-	WT_TIME_OUT, 		/* WT_TIMER_LIST */
150
-	DEL_TIME_OUT,		/* DELETE_LIST */
151
-	RETR_T1, 			/* RT_T1_TO_1 */
152
-	RETR_T1 << 1, 		/* RT_T1_TO_2 */
153
-	RETR_T1 << 2, 		/* RT_T1_TO_3 */
154
-	RETR_T2 			/* RT_T2 */
155
-						/* NR_OF_TIMER_LISTS */
156
-};
143
+	fr_timeout=MS_TO_TICKS(fr_timeout); 
144
+	fr_inv_timeout=MS_TO_TICKS(fr_inv_timeout);
145
+	wait_timeout=MS_TO_TICKS(wait_timeout);
146
+	delete_timeout=MS_TO_TICKS(delete_timeout);
147
+	rt_t1_timeout=MS_TO_TICKS(rt_t1_timeout);
148
+	rt_t2_timeout=MS_TO_TICKS(rt_t2_timeout);
149
+	/* fix 0 values to 1 tick (minimum possible wait time ) */
150
+	if (fr_timeout==0) fr_timeout=1;
151
+	if (fr_inv_timeout==0) fr_inv_timeout=1;
152
+	if (wait_timeout==0) wait_timeout=1;
153
+	if (delete_timeout==0) delete_timeout=1;
154
+	if (rt_t2_timeout==0) rt_t2_timeout=1;
155
+	if (rt_t1_timeout==0) rt_t1_timeout=1;
156
+	
157
+	memset(&user_fr_timeout, 0, sizeof(user_fr_timeout));
158
+	memset(&user_fr_inv_timeout, 0, sizeof(user_fr_inv_timeout));
159
+	
160
+	DBG("tm: tm_init_timers: fr=%d fr_inv=%d wait=%d delete=%d t1=%d t2=%d\n",
161
+			fr_timeout, fr_inv_timeout, wait_timeout, delete_timeout,
162
+			rt_t1_timeout, rt_t2_timeout);
163
+	return 0;
164
+}
157 165
 
158 166
 /******************** handlers ***************************/
159 167
 
160 168
 
161
-static void unlink_timers( struct cell *t );
162 169
 
163
-static void delete_cell( struct cell *p_cell, int unlock )
170
+inline static void cleanup_localcancel_timers( struct cell *t )
164 171
 {
172
+	int i;
173
+	for (i=0; i<t->nr_of_outgoings; i++ )
174
+		stop_rb_timers(&t->uac[i].local_cancel);
175
+}
165 176
 
166
-#ifdef EXTRA_DEBUG
177
+
178
+
179
+inline static void unlink_timers( struct cell *t )
180
+{
167 181
 	int i;
168
-#endif
169 182
 
183
+	stop_rb_timers(&t->uas.response);
184
+	for (i=0; i<t->nr_of_outgoings; i++)
185
+		stop_rb_timers(&t->uac[i].request);
186
+	cleanup_localcancel_timers(t);
187
+}
188
+
189
+
190
+
191
+/* returns number of ticks before retrying the del, or 0 if the del.
192
+ * was succesfull */
193
+inline static ticks_t  delete_cell( struct cell *p_cell, int unlock )
194
+{
170 195
 	/* there may still be FR/RETR timers, which have been reset
171 196
 	   (i.e., time_out==TIMER_DELETED) but are stilled linked to
172 197
 	   timer lists and must be removed from there before the
173 198
 	   structures are released
174 199
 	*/
175 200
 	unlink_timers( p_cell );
176
-
177
-#ifdef EXTRA_DEBUG
178
-
179
-	if (is_in_timer_list2(& p_cell->wait_tl )) {
180
-		LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
181
-			" still on WAIT, timeout=%d\n", p_cell, p_cell->wait_tl.time_out);
182
-		abort();
183
-	}
184
-	if (is_in_timer_list2(& p_cell->uas.response.retr_timer )) {
185
-		LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
186
-			" still on RETR (rep), timeout=%d\n",
187
-			p_cell, p_cell->uas.response.retr_timer.time_out);
188
-		abort();
189
-	}
190
-	if (is_in_timer_list2(& p_cell->uas.response.fr_timer )) {
191
-		LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
192
-			" still on FR (rep), timeout=%d\n", p_cell,
193
-			p_cell->uas.response.fr_timer.time_out);
194
-		abort();
195
-	}
196
-	for (i=0; i<p_cell->nr_of_outgoings; i++) {
197
-		if (is_in_timer_list2(& p_cell->uac[i].request.retr_timer)) {
198
-			LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
199
-				" still on RETR (req %d), timeout %d\n", p_cell, i,
200
-				p_cell->uac[i].request.retr_timer.time_out);
201
-			abort();
202
-		}
203
-		if (is_in_timer_list2(& p_cell->uac[i].request.fr_timer)) {
204
-			LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
205
-				" still on FR (req %d), timeout %d\n", p_cell, i,
206
-				p_cell->uac[i].request.fr_timer.time_out);
207
-			abort();
208
-		}
209
-		if (is_in_timer_list2(& p_cell->uac[i].local_cancel.retr_timer)) {
210
-			LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
211
-				" still on RETR/cancel (req %d), timeout %d\n", p_cell, i,
212
-				p_cell->uac[i].request.retr_timer.time_out);
213
-			abort();
214
-		}
215
-		if (is_in_timer_list2(& p_cell->uac[i].local_cancel.fr_timer)) {
216
-			LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
217
-				" still on FR/cancel (req %d), timeout %d\n", p_cell, i,
218
-				p_cell->uac[i].request.fr_timer.time_out);
219
-			abort();
220
-		}
221
-	}
222
-	/* reset_retr_timers( hash__XX_table, p_cell ); */
223
-#endif
224 201
 	/* still in use ... don't delete */
225 202
 	if ( IS_REFFED_UNSAFE(p_cell) ) {
226 203
 		if (unlock) UNLOCK_HASH(p_cell->hash_index);
227
-		DBG("DEBUG: delete_cell %p: can't delete -- still reffed\n",
228
-			p_cell);
229
-		/* it's added to del list for future del */
230
-		set_timer( &(p_cell->dele_tl), DELETE_LIST, 0 );
204
+		DBG("DEBUG: delete_cell %p: can't delete -- still reffed (%d)\n",
205
+				p_cell, p_cell->ref_count);
206
+		/* delay the delete */
207
+		/* TODO: change refcnts and delete on refcnt==0 */
208
+		return delete_timeout;
231 209
 	} else {
232 210
 		if (unlock) UNLOCK_HASH(p_cell->hash_index);
211
+#ifdef EXTRA_DEBUG
233 212
 		DBG("DEBUG: delete transaction %p\n", p_cell );
213
+#endif
234 214
 		free_cell( p_cell );
215
+		return 0;
235 216
 	}
236 217
 }
237 218
 
219
+
220
+
238 221
 static void fake_reply(struct cell *t, int branch, int code )
239 222
 {
240 223
 	branch_bm_t cancel_bitmap;
... ...
@@ -283,92 +267,72 @@ static void fake_reply(struct cell *t, int branch, int code )
283 283
 
284 284
 
285 285
 
286
-
287
-inline static void retransmission_handler( struct timer_link *retr_tl )
286
+/* return (ticks_t)-1 on error/disable and 0 on success */
287
+inline static ticks_t retransmission_handler( struct retr_buf *r_buf )
288 288
 {
289
-	struct retr_buf* r_buf ;
290
-	enum lists id;
291
-
292
-	r_buf = get_retr_timer_payload(retr_tl);
293 289
 #ifdef EXTRA_DEBUG
294
-	if (r_buf->my_T->damocles) {
290
+	if (r_buf->my_T->flags & T_IN_AGONY) {
295 291
 		LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
296
-			" called from RETR timer\n",r_buf->my_T);
292
+			" called from RETR timer (flags %x)\n",
293
+			r_buf->my_T, r_buf->my_T->flags );
297 294
 		abort();
298 295
 	}	
299 296
 #endif
300
-
301
-	/*the transaction is already removed from RETRANSMISSION_LIST by timer*/
302
-	/* retransmission */
303 297
 	if ( r_buf->activ_type==TYPE_LOCAL_CANCEL 
304 298
 		|| r_buf->activ_type==TYPE_REQUEST ) {
299
+#ifdef EXTRA_DEBUG
305 300
 			DBG("DEBUG: retransmission_handler : "
306 301
 				"request resending (t=%p, %.9s ... )\n", 
307 302
 				r_buf->my_T, r_buf->buffer);
303
+#endif
308 304
 			if (SEND_BUFFER( r_buf )==-1) {
309
-				reset_timer( &r_buf->fr_timer );
305
+				/* disable retr. timers => return -1 */
310 306
 				fake_reply(r_buf->my_T, r_buf->branch, 503 );
311
-				return;
307
+				return (ticks_t)-1;
312 308
 			}
313 309
 	} else {
310
+#ifdef EXTRA_DEBUG
314 311
 			DBG("DEBUG: retransmission_handler : "
315 312
 				"reply resending (t=%p, %.9s ... )\n", 
316 313
 				r_buf->my_T, r_buf->buffer);
314
+#endif
317 315
 			t_retransmit_reply(r_buf->my_T);
318 316
 	}
319
-
320
-	id = r_buf->retr_list;
321
-	r_buf->retr_list = id < RT_T2 ? id + 1 : RT_T2;
322 317
 	
323
-	retr_tl->timer_list= NULL; /* set to NULL so that set_timer will work */
324
-	set_timer( retr_tl, id < RT_T2 ? id + 1 : RT_T2, 0 );
325
-
326
-	DBG("DEBUG: retransmission_handler : done\n");
318
+	return 0;
327 319
 }
328 320
 
329 321
 
330 322
 
331
-
332
-inline static void final_response_handler( struct timer_link *fr_tl )
323
+inline static void final_response_handler(	struct retr_buf* r_buf,
324
+											struct cell* t)
333 325
 {
334
-	int silent, reply_code;
335
-	struct retr_buf* r_buf;
336
-	struct cell *t;
337
-
338
-	if (fr_tl==0){
339
-		/* or BUG?, ignoring it for now */
340
-		LOG(L_CRIT, "ERROR: final_response_handler(0) called\n");
341
-		return;
342
-	}
343
-	r_buf = get_fr_timer_payload(fr_tl);
344
-	t=r_buf->my_T;
326
+	int silent;
327
+	int reply_code;
345 328
 
346 329
 #	ifdef EXTRA_DEBUG
347
-	if (t->damocles) 
330
+	if (t->flags & T_IN_AGONY) 
348 331
 	{
349 332
 		LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
350
-			" called from FR timer\n",r_buf->my_T);
333
+			" called from FR timer (flags %x)\n", t, t->flags);
351 334
 		abort();
352 335
 	}
353 336
 #	endif
354
-
355
-	reset_timer(  &(r_buf->retr_timer) );
356
-
357
-	/* the transaction is already removed from FR_LIST by the timer */
358
-
359 337
 	/* FR for local cancels.... */
360 338
 	if (r_buf->activ_type==TYPE_LOCAL_CANCEL)
361 339
 	{
340
+#ifdef TIMER_DEBUG
362 341
 		DBG("DEBUG: final_response_handler: stop retr for Local Cancel\n");
342
+#endif
363 343
 		return;
364 344
 	}
365
-
366 345
 	/* FR for replies (negative INVITE replies) */
367 346
 	if (r_buf->activ_type>0) {
368 347
 #		ifdef EXTRA_DEBUG
369 348
 		if (t->uas.request->REQ_METHOD!=METHOD_INVITE
370 349
 			|| t->uas.status < 200 ) {
371
-			LOG(L_ERR, "ERROR: final_response_handler: unknown type reply buffer\n");
350
+			LOG(L_CRIT, "BUG: final_response_handler: unknown type reply"
351
+					" buffer\n");
372 352
 			abort();
373 353
 		}
374 354
 #		endif
... ...
@@ -402,15 +366,17 @@ inline static void final_response_handler( struct timer_link *fr_tl )
402 402
 		&& has_noisy_ctimer(t) == 0;
403 403
 	if (silent) {
404 404
 		UNLOCK_REPLIES(t);
405
+#ifdef EXTRA_DEBUG
405 406
 		DBG("DEBUG: final_response_handler: transaction silently dropped (%p)\n",t);
407
+#endif
406 408
 		put_on_wait( t );
407 409
 		return;
408 410
 	}
409
-
411
+#ifdef EXTRA_DEBUG
410 412
 	DBG("DEBUG: final_response_handler:stop retr. and send CANCEL (%p)\n", t);
411
-
413
+#endif
412 414
 	if (is_invite(t) && 
413
-	    r_buf->branch < MAX_BRANCHES && r_buf->branch >= 0 &&
415
+	    r_buf->branch < MAX_BRANCHES && /* r_buf->branch is always >=0 */
414 416
 	    t->uac[r_buf->branch].last_received > 0) {
415 417
 		reply_code = 480; /* Request Terminated */
416 418
 	} else {
... ...
@@ -418,554 +384,143 @@ inline static void final_response_handler( struct timer_link *fr_tl )
418 418
 	}
419 419
 
420 420
 	fake_reply(t, r_buf->branch, reply_code );
421
-
422
-	DBG("DEBUG: final_response_handler : done\n");
423
-}
424
-
425
-
426
-
427
-void cleanup_localcancel_timers( struct cell *t )
428
-{
429
-	int i;
430
-	for (i=0; i<t->nr_of_outgoings; i++ )  {
431
-		reset_timer(  &t->uac[i].local_cancel.retr_timer );
432
-		reset_timer(  &t->uac[i].local_cancel.fr_timer );
433
-	}
434
-}
435
-
436
-
437
-inline static void wait_handler( struct timer_link *wait_tl )
438
-{
439
-	struct cell *p_cell;
440
-
441
-	p_cell = get_wait_timer_payload( wait_tl );
442
-#ifdef EXTRA_DEBUG
443
-	if (p_cell->damocles) {
444
-		LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
445
-			" called from WAIT timer\n",p_cell);
446
-		abort();
447
-	}	
448
-	DBG("DEBUG: WAIT timer hit\n");
449
-#endif
450
-
451
-	/* stop cancel timers if any running */
452
-	if ( is_invite(p_cell) ) cleanup_localcancel_timers( p_cell );
453
-
454
-	/* the transaction is already removed from WT_LIST by the timer */
455
-	/* remove the cell from the hash table */
456
-	DBG("DEBUG: wait_handler : removing %p from table \n", p_cell );
457
-	LOCK_HASH( p_cell->hash_index );
458
-	remove_from_hash_table_unsafe(  p_cell );
459
-	/* jku: no more here -- we do it when we put a transaction on wait */
460
-#ifdef EXTRA_DEBUG
461
-	p_cell->damocles = 1;
462
-#endif
463
-	/* delete (returns with UNLOCK-ed_HASH) */
464
-	delete_cell( p_cell, 1 /* unlock on return */ );
465
-	DBG("DEBUG: wait_handler : done\n");
466
-}
467
-
468
-
469
-
470
-inline static void delete_handler( struct timer_link *dele_tl )
471
-{
472
-	struct cell *p_cell;
473
-
474
-	p_cell = get_dele_timer_payload( dele_tl );
475
-	DBG("DEBUG: delete_handler : removing %p \n", p_cell );
476
-#ifdef EXTRA_DEBUG
477
-	if (p_cell->damocles==0) {
478
-		LOG( L_ERR, "ERROR: transaction %p not scheduled for deletion"
479
-			" and called from DELETE timer\n",p_cell);
480
-		abort();
481
-	}	
482
-#endif
483
-
484
-	/* we call delete now without any locking on hash/ref_count;
485
-	   we can do that because delete_handler is only entered after
486
-	   the delete timer was installed from wait_handler, which
487
-	   removed transaction from hash table and did not destroy it
488
-	   because some processes were using it; that means that the
489
-	   processes currently using the transaction can unref and no
490
-	   new processes can ref -- we can wait until ref_count is
491
-	   zero safely without locking
492
-	*/
493
-	delete_cell( p_cell, 0 /* don't unlock on return */ );
494
-    DBG("DEBUG: delete_handler : done\n");
495 421
 }
496 422
 
497 423
 
498
-/***********************************************************/
499 424
 
500
-struct timer_table *get_timertable()
425
+/* handles retransmissions and fr timers */
426
+/* the following assumption are made (to avoid deleting/re-adding the timer):
427
+ *  retr_buf->retr_interval < ( 1<<((sizeof(ticks_t)*8-1) )
428
+ *  if retr_buf->retr_interval==0 => timer disabled
429
+ *                            ==(ticks_t) -1 => retr. disabled (fr working)
430
+ *     retr_buf->retr_interval & (1 <<(sizeof(ticks_t)*8-1) => retr. & fr reset
431
+ *     (we never reset only retr, it's either reset both of them or retr 
432
+ *      disabled & reset fr). In this case the fr_origin will contain the 
433
+ *      "time" of the reset and next retr should occur at 
434
+ *      fr->origin+retr_interval (we also assume that we'll never reset retr
435
+ *      to a lower value then the current one)
436
+ */
437
+ticks_t retr_buf_handler(ticks_t ticks, struct timer_ln* tl, void *p)
501 438
 {
502
-	return timertable;
503
-}
504
-
439
+	struct retr_