Browse code

core, lib, modules: restructured source code tree

- new folder src/ to hold the source code for main project applications
- main.c is in src/
- all core files are subfolder are in src/core/
- modules are in src/modules/
- libs are in src/lib/
- application Makefiles are in src/
- application binary is built in src/ (src/kamailio)

Daniel-Constantin Mierla authored on 07/12/2016 11:03:51
Showing 1 changed files
1 1
deleted file mode 100644
... ...
@@ -1,676 +0,0 @@
1
-/*
2
- * Copyright (C) 2001-2003 FhG Fokus
3
- *
4
- * This file is part of Kamailio, a free SIP server.
5
- *
6
- * Kamailio is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License as published by
8
- * the Free Software Foundation; either version 2 of the License, or
9
- * (at your option) any later version
10
- *
11
- * Kamailio is distributed in the hope that it will be useful,
12
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
- * GNU General Public License for more details.
15
- *
16
- * You should have received a copy of the GNU General Public License 
17
- * along with this program; if not, write to the Free Software 
18
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19
- */
20
-
21
-/**
22
- * \file
23
- * \brief TM :: timer support
24
- * 
25
- * TM timer support. It has been designed for high performance using
26
- * some techniques of which timer users need to be aware.
27
- * - One technique is "fixed-timer-length". We maintain separate 
28
- * timer lists, all of them include elements of the same time
29
- * to fire. That allows *appending* new events to the list as
30
- * opposed to inserting them by time, which is costly due to
31
- * searching time spent in a mutex. The performance benefit is
32
- * noticeable. The limitation is you need a new timer list for
33
- * each new timer length.
34
- * - Another technique is the timer process slices off expired elements
35
- * from the list in a mutex, but executes the timer after the mutex
36
- * is left. That saves time greatly as whichever process wants to
37
- * add/remove a timer, it does not have to wait until the current
38
- * list is processed. However, be aware the timers may hit in a delayed
39
- * manner; you have no guarantee in your process that after resetting a timer, 
40
- * it will no more hit. It might have been removed by timer process,
41
- * and is waiting to be executed.
42
- * 
43
- * The following example shows it:
44
- * 
45
- *		PROCESS1				TIMER PROCESS
46
- * 
47
- * -	0.						timer hits, it is removed from queue and
48
- * 							about to be executed
49
- * -	1.	process1 decides to
50
- * 		reset the timer 
51
- * -	2.						timer is executed now
52
- * -	3.	if the process1 naively
53
- * 		thinks the timer could not 
54
- * 		have been executed after 
55
- * 		resetting the timer, it is
56
- * 		WRONG -- it was (step 2.)
57
- * 
58
- * So be careful when writing the timer handlers. Currently defined timers 
59
- * don't hurt if they hit delayed, I hope at least. Retransmission timer 
60
- * may results in a useless retransmission -- not too bad. FR timer not too
61
- * bad either as timer processing uses a REPLY mutex making it safe to other
62
- * processing affecting transaction state. Wait timer not bad either -- processes
63
- * putting a transaction on wait don't do anything with it anymore.
64
- * 
65
- * 	Example when it does not hurt:
66
- * 
67
- * 		PROCESS1				TIMER PROCESS
68
- * 
69
- * -	0.						RETR timer removed from list and
70
- * 							scheduled for execution
71
- * -	1. 200/BYE received->
72
- * 	   reset RETR, put_on_wait
73
- * -	2.						RETR timer executed -- too late but it does
74
- * 							not hurt
75
- * -	3.						WAIT handler executed
76
- *
77
- * The rule of thumb is don't touch data you put under a timer. Create data,
78
- * put them under a timer, and let them live until they are safely destroyed from
79
- * wait/delete timer.  The only safe place to manipulate the data is 
80
- * from timer process in which delayed timers cannot hit (all timers are
81
- * processed sequentially).
82
- * 
83
- * A "bad example" -- rewriting content of retransmission buffer
84
- * in an unprotected way is bad because a delayed retransmission timer might 
85
- * hit. Thats why our reply retransmission procedure is enclosed in 
86
- * a REPLY_LOCK.
87
- * \ingroup tm
88
- */
89
-
90
-
91
-#include "defs.h"
92
-
93
-
94
-#include "config.h"
95
-#include "h_table.h"
96
-#include "timer.h"
97
-#include "../../dprint.h"
98
-#include "lock.h"
99
-#include "t_stats.h"
100
-
101
-#include "../../hash_func.h"
102
-#include "../../dprint.h"
103
-#include "../../config.h"
104
-#include "../../parser/parser_f.h"
105
-#include "../../ut.h"
106
-#include "../../timer_ticks.h"
107
-#include "../../compiler_opt.h" 
108
-#include "../../sr_compat.h" 
109
-#include "t_funcs.h"
110
-#include "t_reply.h"
111
-#include "t_cancel.h"
112
-#include "t_hooks.h"
113
-#ifdef USE_DNS_FAILOVER
114
-#include "t_fwd.h" /* t_send_branch */
115
-#include "../../cfg_core.h" /* cfg_get(core, core_cfg, use_dns_failover) */
116
-#endif
117
-#ifdef USE_DST_BLACKLIST
118
-#include "../../dst_blacklist.h"
119
-#endif
120
-
121
-
122
-
123
-struct msgid_var user_fr_timeout;
124
-struct msgid_var user_fr_inv_timeout;
125
-#ifdef TM_DIFF_RT_TIMEOUT
126
-struct msgid_var user_rt_t1_timeout_ms;
127
-struct msgid_var user_rt_t2_timeout_ms;
128
-#endif
129
-struct msgid_var user_inv_max_lifetime;
130
-struct msgid_var user_noninv_max_lifetime;
131
-
132
-
133
-/**
134
- * \brief Check helper for configuration framework values
135
- * 
136
- * Check helper for configuration framework values for internal use
137
- * The val should be unsigned or positive, use
138
- * <= instead of < to get read of gcc warning when 
139
- * sizeof(cell_member)==sizeof(val) (Note that this limits
140
- * maximum value to max. type -1)
141
- */
142
-#define SIZE_FIT_CHECK(cell_member, val, cfg_name) \
143
-	if (MAX_UVAR_VALUE(((struct cell*)0)->cell_member) <= (val)){ \
144
-		ERR("tm_init_timers: " cfg_name " too big: %lu (%lu ticks) " \
145
-				"- max %lu (%lu ticks) \n", TICKS_TO_MS((unsigned long)(val)),\
146
-				(unsigned long)(val), \
147
-				TICKS_TO_MS(MAX_UVAR_VALUE(((struct cell*)0)->cell_member)), \
148
-				MAX_UVAR_VALUE(((struct cell*)0)->cell_member)); \
149
-		goto error; \
150
-	} 
151
-
152
-/**
153
- * \brief fix timer values to ticks
154
- */
155
-int tm_init_timers(void)
156
-{
157
-	default_tm_cfg.fr_timeout=MS_TO_TICKS(default_tm_cfg.fr_timeout); 
158
-	default_tm_cfg.fr_inv_timeout=MS_TO_TICKS(default_tm_cfg.fr_inv_timeout);
159
-	default_tm_cfg.wait_timeout=MS_TO_TICKS(default_tm_cfg.wait_timeout);
160
-	default_tm_cfg.delete_timeout=MS_TO_TICKS(default_tm_cfg.delete_timeout);
161
-	default_tm_cfg.tm_max_inv_lifetime=MS_TO_TICKS(default_tm_cfg.tm_max_inv_lifetime);
162
-	default_tm_cfg.tm_max_noninv_lifetime=MS_TO_TICKS(default_tm_cfg.tm_max_noninv_lifetime);
163
-	/* fix 0 values to 1 tick (minimum possible wait time ) */
164
-	if (default_tm_cfg.fr_timeout==0) default_tm_cfg.fr_timeout=1;
165
-	if (default_tm_cfg.fr_inv_timeout==0) default_tm_cfg.fr_inv_timeout=1;
166
-	if (default_tm_cfg.wait_timeout==0) default_tm_cfg.wait_timeout=1;
167
-	if (default_tm_cfg.delete_timeout==0) default_tm_cfg.delete_timeout=1;
168
-	if (default_tm_cfg.rt_t2_timeout_ms==0) default_tm_cfg.rt_t2_timeout_ms=1;
169
-	if (default_tm_cfg.rt_t1_timeout_ms==0) default_tm_cfg.rt_t1_timeout_ms=1;
170
-	if (default_tm_cfg.tm_max_inv_lifetime==0) default_tm_cfg.tm_max_inv_lifetime=1;
171
-	if (default_tm_cfg.tm_max_noninv_lifetime==0) default_tm_cfg.tm_max_noninv_lifetime=1;
172
-	
173
-	/* size fit checks */
174
-	SIZE_FIT_CHECK(fr_timeout, default_tm_cfg.fr_timeout, "fr_timer");
175
-	SIZE_FIT_CHECK(fr_inv_timeout, default_tm_cfg.fr_inv_timeout, "fr_inv_timer");
176
-#ifdef TM_DIFF_RT_TIMEOUT
177
-	SIZE_FIT_CHECK(rt_t1_timeout_ms, default_tm_cfg.rt_t1_timeout_ms,
178
-					"retr_timer1");
179
-	SIZE_FIT_CHECK(rt_t2_timeout_ms, default_tm_cfg.rt_t2_timeout_ms,
180
-					"retr_timer2");
181
-#endif
182
-	SIZE_FIT_CHECK(end_of_life, default_tm_cfg.tm_max_inv_lifetime, "max_inv_lifetime");
183
-	SIZE_FIT_CHECK(end_of_life, default_tm_cfg.tm_max_noninv_lifetime, "max_noninv_lifetime");
184
-	
185
-	memset(&user_fr_timeout, 0, sizeof(user_fr_timeout));
186
-	memset(&user_fr_inv_timeout, 0, sizeof(user_fr_inv_timeout));
187
-#ifdef TM_DIFF_RT_TIMEOUT
188
-	memset(&user_rt_t1_timeout_ms, 0, sizeof(user_rt_t1_timeout_ms));
189
-	memset(&user_rt_t2_timeout_ms, 0, sizeof(user_rt_t2_timeout_ms));
190
-#endif
191
-	memset(&user_inv_max_lifetime, 0, sizeof(user_inv_max_lifetime));
192
-	memset(&user_noninv_max_lifetime, 0, sizeof(user_noninv_max_lifetime));
193
-	
194
-	DBG("tm: tm_init_timers: fr=%d fr_inv=%d wait=%d delete=%d t1=%d t2=%d"
195
-			" max_inv_lifetime=%d max_noninv_lifetime=%d\n",
196
-			default_tm_cfg.fr_timeout, default_tm_cfg.fr_inv_timeout,
197
-			default_tm_cfg.wait_timeout, default_tm_cfg.delete_timeout,
198
-			default_tm_cfg.rt_t1_timeout_ms, default_tm_cfg.rt_t2_timeout_ms,
199
-			default_tm_cfg.tm_max_inv_lifetime, default_tm_cfg.tm_max_noninv_lifetime);
200
-	return 0;
201
-error:
202
-	return -1;
203
-}
204
-
205
-/**
206
- * \brief Internal macro for timer_fixup()
207
- * 
208
- * Internal macro for timer_fixup(), performs size fit
209
- * check if the timer name matches
210
- */
211
-#define IF_IS_TIMER_NAME(cell_member, cfg_name) \
212
-	if ((name->len == sizeof(cfg_name)-1) && \
213
-		(memcmp(name->s, cfg_name, sizeof(cfg_name)-1)==0)) { \
214
-			SIZE_FIT_CHECK(cell_member, t, cfg_name); \
215
-	}
216
-
217
-/**
218
- * \brief Fixup function for the timer values
219
- * 
220
- * Fixup function for the timer values, (called by the
221
- * configuration framework)
222
- * \param handle not used
223
- * \param gname not used
224
- * \param name not used
225
- * \param val fixed timer value
226
- * \return 0 on success, -1 on error
227
- */
228
-int timer_fixup(void *handle, str *gname, str *name, void **val)
229
-{
230
-	ticks_t t;
231
-
232
-	t = MS_TO_TICKS((unsigned int)(long)(*val));
233
-	/* fix 0 values to 1 tick (minimum possible wait time ) */
234
-	if (t == 0) t = 1;
235
-
236
-	/* size fix checks */
237
-	IF_IS_TIMER_NAME(fr_timeout, "fr_timer")
238
-	else IF_IS_TIMER_NAME(fr_inv_timeout, "fr_inv_timer")
239
-	else IF_IS_TIMER_NAME(end_of_life, "max_inv_lifetime")
240
-	else IF_IS_TIMER_NAME(end_of_life, "max_noninv_lifetime")
241
-
242
-	*val = (void *)(long)t;
243
-	return 0;
244
-
245
-error:
246
-	return -1;
247
-}
248
-
249
-
250
-
251
-/** fixup function for timer values that are kept in ms.
252
- * (called by the configuration framework)
253
- * It checks if the value fits in the tm structures 
254
- */
255
-int timer_fixup_ms(void *handle, str *gname, str *name, void **val)
256
-{
257
-	long	t;
258
-
259
-	t = (long)(*val);
260
-
261
-	/* size fix checks */
262
-#ifdef TM_DIFF_RT_TIMEOUT
263
-	IF_IS_TIMER_NAME(rt_t1_timeout_ms, "retr_timer1")
264
-	else IF_IS_TIMER_NAME(rt_t2_timeout_ms, "retr_timer2")
265
-#endif
266
-
267
-	return 0;
268
-
269
-error:
270
-	return -1;
271
-}
272
-
273
-/******************** handlers ***************************/
274
-
275
-
276
-#ifndef TM_DEL_UNREF
277
-/* returns number of ticks before retrying the del, or 0 if the del.
278
- * was succesfull */
279
-inline static ticks_t  delete_cell( struct cell *p_cell, int unlock )
280
-{
281
-	/* there may still be FR/RETR timers, which have been reset
282
-	   (i.e., time_out==TIMER_DELETED) but are stilled linked to
283
-	   timer lists and must be removed from there before the
284
-	   structures are released
285
-	*/
286
-	unlink_timers( p_cell );
287
-	/* still in use ... don't delete */
288
-	if ( IS_REFFED_UNSAFE(p_cell) ) {
289
-		if (unlock) UNLOCK_HASH(p_cell->hash_index);
290
-		DBG("DEBUG: delete_cell %p: can't delete -- still reffed (%d)\n",
291
-				p_cell, p_cell->ref_count);
292
-		/* delay the delete */
293
-		/* TODO: change refcnts and delete on refcnt==0 */
294
-		return cfg_get(tm, tm_cfg, delete_timeout);
295
-	} else {
296
-		if (unlock) UNLOCK_HASH(p_cell->hash_index);
297
-#ifdef EXTRA_DEBUG
298
-		DBG("DEBUG: delete transaction %p\n", p_cell );
299
-#endif
300
-		free_cell( p_cell );
301
-		return 0;
302
-	}
303
-}
304
-#endif /* TM_DEL_UNREF */
305
-
306
-
307
-
308
-
309
-/* generate a fake reply
310
- * it assumes the REPLY_LOCK is already held and returns unlocked */
311
-static void fake_reply(struct cell *t, int branch, int code )
312
-{
313
-	struct cancel_info cancel_data;
314
-	short do_cancel_branch;
315
-	enum rps reply_status;
316
-
317
-	init_cancel_info(&cancel_data);
318
-	do_cancel_branch = is_invite(t) && prepare_cancel_branch(t, branch, 0);
319
-	/* mark branch as canceled */
320
-	t->uac[branch].request.flags|=F_RB_CANCELED;
321
-	t->uac[branch].request.flags|=F_RB_RELAYREPLY;
322
-	if ( is_local(t) ) {
323
-		reply_status=local_reply( t, FAKED_REPLY, branch, 
324
-					  code, &cancel_data );
325
-	} else {
326
-		/* rely reply, but don't put on wait, we still need t
327
-		 * to send the cancels */
328
-		reply_status=relay_reply( t, FAKED_REPLY, branch, code,
329
-					  &cancel_data, 0 );
330
-	}
331
-	/* now when out-of-lock do the cancel I/O */
332
-#ifdef CANCEL_REASON_SUPPORT
333
-	if (do_cancel_branch) cancel_branch(t, branch, &cancel_data.reason, 0);
334
-#else /* CANCEL_REASON_SUPPORT */
335
-	if (do_cancel_branch) cancel_branch(t, branch, 0);
336
-#endif /* CANCEL_REASON_SUPPORT */
337
-	/* it's cleaned up on error; if no error occurred and transaction
338
-	   completed regularly, I have to clean-up myself
339
-	*/
340
-	if (reply_status == RPS_COMPLETED)
341
-		put_on_wait(t);
342
-}
343
-
344
-
345
-
346
-/* return (ticks_t)-1 on error/disable and 0 on success */
347
-inline static ticks_t retransmission_handler( struct retr_buf *r_buf )
348
-{
349
-#ifdef EXTRA_DEBUG
350
-	if (r_buf->my_T->flags & T_IN_AGONY) {
351
-		LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
352
-			" called from RETR timer (flags %x)\n",
353
-			r_buf->my_T, r_buf->my_T->flags );
354
-		abort();
355
-	}	
356
-#endif
357
-	if ( r_buf->activ_type==TYPE_LOCAL_CANCEL 
358
-		|| r_buf->activ_type==TYPE_REQUEST ) {
359
-#ifdef EXTRA_DEBUG
360
-			DBG("DEBUG: retransmission_handler : "
361
-				"request resending (t=%p, %.9s ... )\n", 
362
-				r_buf->my_T, r_buf->buffer);
363
-#endif
364
-			if (SEND_BUFFER( r_buf )==-1) {
365
-				/* disable retr. timers => return -1 */
366
-				fake_reply(r_buf->my_T, r_buf->branch, 503 );
367
-				return (ticks_t)-1;
368
-			}
369
-			if (unlikely(has_tran_tmcbs(r_buf->my_T, TMCB_REQUEST_SENT))) 
370
-				run_trans_callbacks_with_buf(TMCB_REQUEST_SENT, r_buf, 
371
-				0, 0, TMCB_RETR_F);
372
-	} else {
373
-#ifdef EXTRA_DEBUG
374
-			DBG("DEBUG: retransmission_handler : "
375
-				"reply resending (t=%p, %.9s ... )\n", 
376
-				r_buf->my_T, r_buf->buffer);
377
-#endif
378
-			t_retransmit_reply(r_buf->my_T);
379
-	}
380
-	
381
-	return 0;
382
-}
383
-
384
-
385
-
386
-inline static void final_response_handler(	struct retr_buf* r_buf,
387
-											struct cell* t)
388
-{
389
-	int silent;
390
-#ifdef USE_DNS_FAILOVER
391
-	/*int i; 
392
-	int added_branches;
393
-	*/
394
-	int branch_ret;
395
-	int prev_branch;
396
-	ticks_t now;
397
-#endif
398
-
399
-#	ifdef EXTRA_DEBUG
400
-	if (t->flags & T_IN_AGONY) 
401
-	{
402
-		LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
403
-			" called from FR timer (flags %x)\n", t, t->flags);
404
-		abort();
405
-	}
406
-#	endif
407
-	/* FR for local cancels.... */
408
-	if (r_buf->activ_type==TYPE_LOCAL_CANCEL)
409
-	{
410
-#ifdef TIMER_DEBUG
411
-		DBG("DEBUG: final_response_handler: stop retr for Local Cancel\n");
412
-#endif
413
-		return;
414
-	}
415
-	/* FR for replies (negative INVITE replies) */
416
-	if (r_buf->activ_type>0) {
417
-#		ifdef EXTRA_DEBUG
418
-		if (t->uas.request->REQ_METHOD!=METHOD_INVITE
419
-			|| t->uas.status < 200 ) {
420
-			LOG(L_CRIT, "BUG: final_response_handler: unknown type reply"
421
-					" buffer\n");
422
-			abort();
423
-		}
424
-#		endif
425
-		put_on_wait( t );
426
-		return;
427
-	};
428
-
429
-	/* lock reply processing to determine how to proceed reliably */
430
-	LOCK_REPLIES( t );
431
-	/* now it can be only a request retransmission buffer;
432
-	   try if you can simply discard the local transaction 
433
-	   state without compellingly removing it from the
434
-	   world */
435
-	silent=
436
-		/* don't go silent if disallowed globally ... */
437
-		cfg_get(tm, tm_cfg, noisy_ctimer)==0
438
-		/* ... or for this particular transaction */
439
-		&& has_noisy_ctimer(t) == 0
440
-		/* not for UACs */
441
-		&& !is_local(t)
442
-		/* invites only */
443
-		&& is_invite(t)
444
-		/* parallel forking does not allow silent state discarding */
445
-		&& t->nr_of_outgoings==1
446
-		/* on_negativ reply handler not installed -- serial forking 
447
-		 * could occur otherwise */
448
-		&& t->on_failure==0
449
-		/* the same for FAILURE callbacks */
450
-		&& !has_tran_tmcbs( t, TMCB_ON_FAILURE_RO|TMCB_ON_FAILURE) 
451
-		/* something received -- we will not be silent on error */
452
-		&& t->uac[r_buf->branch].last_received==0;
453
-	
454
-	if (silent) {
455
-		UNLOCK_REPLIES(t);
456
-#ifdef EXTRA_DEBUG
457
-		DBG("DEBUG: final_response_handler: transaction silently dropped (%p)"
458
-				", branch %d, last_received %d\n",t, r_buf->branch,
459
-				 t->uac[r_buf->branch].last_received);
460
-#endif
461
-		put_on_wait( t );
462
-		return;
463
-	}
464
-#ifdef EXTRA_DEBUG
465
-	DBG("DEBUG: final_response_handler:stop retr. and send CANCEL (%p)\n", t);
466
-#endif
467
-	if ((r_buf->branch < sr_dst_max_branches) && /* r_buf->branch is always >=0 */
468
-			(t->uac[r_buf->branch].last_received==0) &&
469
-			(t->uac[r_buf->branch].request.buffer!=NULL) /* not a blind UAC */
470
-	){
471
-		/* no reply received */
472
-#ifdef USE_DST_BLACKLIST
473
-		if (r_buf->my_T
474
-			&& r_buf->my_T->uas.request
475
-			&& (r_buf->my_T->uas.request->REQ_METHOD &
476
-					cfg_get(tm, tm_cfg, tm_blst_methods_add))
477
-		)
478
-			dst_blacklist_add( BLST_ERR_TIMEOUT, &r_buf->dst,
479
-								r_buf->my_T->uas.request);
480
-#endif
481
-#ifdef USE_DNS_FAILOVER
482
-		/* if this is an invite, the destination resolves to more ips, and
483
-		 *  it still hasn't passed more than fr_inv_timeout since we
484
-		 *  started, add another branch/uac */
485
-		if (cfg_get(core, core_cfg, use_dns_failover)){
486
-			now=get_ticks_raw();
487
-			if ((s_ticks_t)(t->end_of_life-now)>0){
488
-				branch_ret=add_uac_dns_fallback(t, t->uas.request,
489
-													&t->uac[r_buf->branch], 0);
490
-				prev_branch=-1;
491
-				while((branch_ret>=0) &&(branch_ret!=prev_branch)){
492
-					prev_branch=branch_ret;
493
-					branch_ret=t_send_branch(t, branch_ret, t->uas.request , 
494
-												0, 0);
495
-				}
496
-			}
497
-		}
498
-#endif
499
-	}
500
-	fake_reply(t, r_buf->branch, 408);
501
-}
502
-
503
-
504
-
505
-/* handles retransmissions and fr timers */
506
-/* the following assumption are made (to avoid deleting/re-adding the timer):
507
- *  retr_buf->retr_interval < ( 1<<((sizeof(ticks_t)*8-1) )
508
- *  if retr_buf->retr_interval==0 => timer disabled
509
- *                            ==(ticks_t) -1 => retr. disabled (fr working)
510
- *     retr_buf->retr_interval & (1 <<(sizeof(ticks_t)*8-1) => retr. & fr reset
511
- *     (we never reset only retr, it's either reset both of them or retr 
512
- *      disabled & reset fr). In this case the fr_origin will contain the 
513
- *      "time" of the reset and next retr should occur at 
514
- *      fr->origin+retr_interval (we also assume that we'll never reset retr
515
- *      to a lower value then the current one)
516
- */
517
-ticks_t retr_buf_handler(ticks_t ticks, struct timer_ln* tl, void *p)
518
-{
519
-	struct retr_buf* rbuf ;
520
-	ticks_t fr_remainder;
521
-	ticks_t retr_remainder;
522
-	ticks_t retr_interval;
523
-	unsigned long new_retr_interval_ms;
524
-	unsigned long crt_retr_interval_ms;
525
-	struct cell *t;
526
-
527
-	rbuf=(struct  retr_buf*)
528
-			((void*)tl-(void*)(&((struct retr_buf*)0)->timer));
529
-	membar_depends(); /* to be on the safe side */
530
-	t=rbuf->my_T;
531
-	
532
-#ifdef TIMER_DEBUG
533
-	DBG("tm: timer retr_buf_handler @%d (%p -> %p -> %p)\n",
534
-			ticks, tl, rbuf, t);
535
-#endif
536
-	if (unlikely(rbuf->flags & F_RB_DEL_TIMER)){
537
-		/* timer marked for deletion */
538
-		rbuf->t_active=0; /* mark it as removed */
539
-		/* a membar is not really needed, in the very unlikely case that 
540
-		 * another process will see old t_active's value and will try to 
541
-		 * delete the timer again, but since timer_del it's safe in this cases
542
-		 * it will be a no-op */
543
-		return 0;
544
-	}
545
-	/* overflow safe check (should work ok for fr_intervals < max ticks_t/2) */
546
-	if ((s_ticks_t)(rbuf->fr_expire-ticks)<=0){
547
-		/* final response */
548
-		rbuf->t_active=0; /* mark the timer as removed 
549
-							 (both timers disabled)
550
-							  a little race risk, but
551
-							  nothing bad would happen */
552
-		rbuf->flags|=F_RB_TIMEOUT;
553
-		/* WARNING:  the next line depends on taking care not to start the 
554
-		 *           wait timer before finishing with t (if this is not 
555
-		 *           guaranteed then comment the timer_allow_del() line) */
556
-		timer_allow_del(); /* [optional] allow timer_dels, since we're done
557
-							  and there is no race risk */
558
-		final_response_handler(rbuf, t);
559
-		return 0;
560
-	}else{
561
-		/*  4 possible states running (t1), t2, paused, disabled */
562
-			if ((s_ticks_t)(rbuf->retr_expire-ticks)<=0){
563
-				if (rbuf->flags & F_RB_RETR_DISABLED)
564
-					goto disabled;
565
-				crt_retr_interval_ms = (unsigned long)p;
566
-				/* get the  current interval from timer param. */
567
-				if (unlikely((rbuf->flags & F_RB_T2) ||
568
-						(crt_retr_interval_ms > RT_T2_TIMEOUT_MS(rbuf)))){
569
-					retr_interval = MS_TO_TICKS(RT_T2_TIMEOUT_MS(rbuf));
570
-					new_retr_interval_ms = RT_T2_TIMEOUT_MS(rbuf);
571
-				}else{
572
-					retr_interval = MS_TO_TICKS(crt_retr_interval_ms);
573
-					new_retr_interval_ms=crt_retr_interval_ms<<1;
574
-				}
575
-#ifdef TIMER_DEBUG
576
-				DBG("tm: timer: retr: new interval %ld ms / %d ticks"
577
-						" (max %d ms)\n", new_retr_interval_ms, retr_interval,
578
-						RT_T2_TIMEOUT_MS(rbuf));
579
-#endif
580
-				/* we could race with the reply_received code, but the 
581
-				 * worst thing that can happen is to delay a reset_to_t2
582
-				 * for crt_interval and send an extra retr.*/
583
-				rbuf->retr_expire=ticks+retr_interval;
584
-				/* set new interval to -1 on error, or retr_int. on success */
585
-				retr_remainder=retransmission_handler(rbuf) | retr_interval;
586
-				/* store the next retr. interval in ms inside the timer struct,
587
-				 * in the data member */
588
-				tl->data=(void*)(new_retr_interval_ms);
589
-			}else{
590
-				retr_remainder= rbuf->retr_expire-ticks;
591
-				DBG("tm: timer: retr: nothing to do, expire in %d\n", 
592
-						retr_remainder);
593
-			}
594
-	}
595
-/* skip: */
596
-	/* return minimum of the next retransmission handler and the 
597
-	 * final response (side benefit: it properly cancels timer if ret==0 and
598
-	 *  sleeps for fr_remainder if retr. is canceled [==(ticks_t)-1]) */
599
-	fr_remainder=rbuf->fr_expire-ticks; /* to be more precise use
600
-											get_ticks_raw() instead of ticks
601
-											(but make sure that 
602
-											crt. ticks < fr_expire */
603
-#ifdef TIMER_DEBUG
604
-	DBG("tm: timer retr_buf_handler @%d (%p ->%p->%p) exiting min (%d, %d)\n",
605
-			ticks, tl, rbuf, t, retr_remainder, fr_remainder);
606
-#endif
607
-#ifdef EXTRA_DEBUG
608
-	if  (retr_remainder==0 || fr_remainder==0){
609
-		BUG("tm: timer retr_buf_handler: 0 remainder => disabling timer!: "
610
-				"retr_remainder=%d, fr_remainder=%d\n", retr_remainder,
611
-				fr_remainder);
612
-	}
613
-#endif
614
-	if (retr_remainder<fr_remainder)
615
-		return retr_remainder;
616
-	else{
617
-		/* hack to switch to the slow timer */
618
-#ifdef TM_FAST_RETR_TIMER
619
-		tl->flags&=~F_TIMER_FAST;
620
-#endif
621
-		return fr_remainder;
622
-	}
623
-disabled:
624
-	return rbuf->fr_expire-ticks;
625
-}
626
-
627
-
628
-
629
-ticks_t wait_handler(ticks_t ti, struct timer_ln *wait_tl, void* data)
630
-{
631
-	struct cell *p_cell;
632
-	ticks_t ret;
633
-
634
-	p_cell=(struct cell*)data;
635
-#ifdef TIMER_DEBUG
636
-	DBG("DEBUG: WAIT timer hit @%d for %p (timer_lm %p)\n", 
637
-			ti, p_cell, wait_tl);
638
-#endif
639
-
640
-#ifdef TM_DEL_UNREF
641
-	/* stop cancel timers if any running */
642
-	if ( is_invite(p_cell) ) cleanup_localcancel_timers( p_cell );
643
-	/* remove the cell from the hash table */
644
-	LOCK_HASH( p_cell->hash_index );
645
-	remove_from_hash_table_unsafe(  p_cell );
646
-	UNLOCK_HASH( p_cell->hash_index );
647
-	p_cell->flags |= T_IN_AGONY;
648
-	UNREF_FREE(p_cell);
649
-	ret=0;
650
-#else /* TM_DEL_UNREF */
651
-	if (p_cell->flags & T_IN_AGONY){
652
-		/* delayed delete */
653
-		/* we call delete now without any locking on hash/ref_count;
654
-		   we can do that because delete_handler is only entered after
655
-		   the delete timer was installed from wait_handler, which
656
-		   removed transaction from hash table and did not destroy it
657
-		   because some processes were using it; that means that the
658
-		   processes currently using the transaction can unref and no
659
-		   new processes can ref -- we can wait until ref_count is
660
-		   zero safely without locking
661
-		*/
662
-		ret=delete_cell( p_cell, 0 /* don't unlock on return */ );
663
-	}else {
664
-		/* stop cancel timers if any running */
665
-		if ( is_invite(p_cell) ) cleanup_localcancel_timers( p_cell );
666
-		/* remove the cell from the hash table */
667
-		LOCK_HASH( p_cell->hash_index );
668
-		remove_from_hash_table_unsafe(  p_cell );
669
-		p_cell->flags |= T_IN_AGONY;
670
-		/* delete (returns with UNLOCK-ed_HASH) */
671
-		ret=delete_cell( p_cell, 1 /* unlock on return */ );
672
-	}
673
-#endif /* TM_DEL_UNREF */
674
-	return ret;
675
-}
676
-
Browse code

tm Remove svn ID, remove history, rename "ser" to "kamailio"

Olle E. Johansson authored on 03/01/2015 15:48:29
Showing 1 changed files
... ...
@@ -1,19 +1,14 @@
1 1
 /*
2 2
  * Copyright (C) 2001-2003 FhG Fokus
3 3
  *
4
- * This file is part of ser, a free SIP server.
4
+ * This file is part of Kamailio, a free SIP server.
5 5
  *
6
- * ser is free software; you can redistribute it and/or modify
6
+ * Kamailio is free software; you can redistribute it and/or modify
7 7
  * it under the terms of the GNU General Public License as published by
8 8
  * the Free Software Foundation; either version 2 of the License, or
9 9
  * (at your option) any later version
10 10
  *
11
- * For a license to use the ser software under conditions
12
- * other than those described here, or to purchase support for this
13
- * software, please contact iptel.org by e-mail at the following addresses:
14
- *    info@iptel.org
15
- *
16
- * ser is distributed in the hope that it will be useful,
11
+ * Kamailio is distributed in the hope that it will be useful,
17 12
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 13
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 14
  * GNU General Public License for more details.
... ...
@@ -23,28 +18,6 @@
23 18
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
24 19
  */
25 20
 
26
-/*
27
- * History:
28
- * --------
29
- *  2003-06-27  timers are not unlinked if timerlist is 0 (andrei)
30
- *  2004-02-13  t->is_invite, t->local, t->noisy_ctimer replaced;
31
- *              timer_link.payload removed (bogdan)
32
- *  2005-10-03  almost completely rewritten to use the new timers (andrei)
33
- *  2005-12-12  on final response marked the rb as removed to avoid deleting
34
- *              it from the timer handle; timer_allow_del()  (andrei)
35
- *  2006-08-11  final_response_handler dns failover support for timeout-ed
36
- *              invites (andrei)
37
- *  2006-09-28  removed the 480 on fr_inv_timeout reply: on timeout always 
38
- *               return a 408
39
- *              set the corresponding "faked" failure route sip_msg->msg_flags 
40
- *               on timeout or if the branch received a reply (andrei)
41
- *  2007-03-15  TMCB_ONSEND callbacks support (andrei)
42
- *  2007-05-29  delete on transaction ref_count==0 : removed the delete timer
43
- *               (andrei)
44
- * 2007-06-01  support for different retransmissions intervals per transaction;
45
- *             added maximum inv. and non-inv. transaction life time (andrei)
46
- */
47
-
48 21
 /**
49 22
  * \file
50 23
  * \brief TM :: timer support
Browse code

tm: transaction uses number of branches specified by max_branches global parameter

- the number of UACs per transaction is based on max_branches global
parameter

Daniel-Constantin Mierla authored on 17/10/2014 09:06:41
Showing 1 changed files
... ...
@@ -491,7 +491,7 @@ inline static void final_response_handler(	struct retr_buf* r_buf,
491 491
 #ifdef EXTRA_DEBUG
492 492
 	DBG("DEBUG: final_response_handler:stop retr. and send CANCEL (%p)\n", t);
493 493
 #endif
494
-	if ((r_buf->branch < MAX_BRANCHES) && /* r_buf->branch is always >=0 */
494
+	if ((r_buf->branch < sr_dst_max_branches) && /* r_buf->branch is always >=0 */
495 495
 			(t->uac[r_buf->branch].last_received==0) &&
496 496
 			(t->uac[r_buf->branch].request.buffer!=NULL) /* not a blind UAC */
497 497
 	){
Browse code

all: updated FSF address in GPL text

Anthony Messina authored on 04/07/2014 09:36:37 • Daniel-Constantin Mierla committed on 04/07/2014 09:37:36
Showing 1 changed files
... ...
@@ -20,7 +20,7 @@
20 20
  *
21 21
  * You should have received a copy of the GNU General Public License 
22 22
  * along with this program; if not, write to the Free Software 
23
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
24 24
  */
25 25
 
26 26
 /*
Browse code

tm: avoid tryin to mitigate relaying 487 for local canceling branches when a reply is forced from config

- it can result in deadlock if there is a local retransmission timeout
and the response code is overwritten by admin in failure route with a
t_reply()
- reported by Jason Penton

Daniel-Constantin Mierla authored on 10/04/2014 06:56:13
Showing 1 changed files
... ...
@@ -345,6 +345,7 @@ static void fake_reply(struct cell *t, int branch, int code )
345 345
 	do_cancel_branch = is_invite(t) && prepare_cancel_branch(t, branch, 0);
346 346
 	/* mark branch as canceled */
347 347
 	t->uac[branch].request.flags|=F_RB_CANCELED;
348
+	t->uac[branch].request.flags|=F_RB_RELAYREPLY;
348 349
 	if ( is_local(t) ) {
349 350
 		reply_status=local_reply( t, FAKED_REPLY, branch, 
350 351
 					  code, &cancel_data );
Browse code

tm: added t_is_set("target") function

- returns true if the attribute specified by the target parameter is set
for current transaction (e.g., failure_route, branch_route,
onreply_route)
- on_negative was replaced with on_failure internally to be consistent
with config file naming

Daniel-Constantin Mierla authored on 29/06/2012 10:25:24
Showing 1 changed files
... ...
@@ -471,7 +471,7 @@ inline static void final_response_handler(	struct retr_buf* r_buf,
471 471
 		&& t->nr_of_outgoings==1
472 472
 		/* on_negativ reply handler not installed -- serial forking 
473 473
 		 * could occur otherwise */
474
-		&& t->on_negative==0
474
+		&& t->on_failure==0
475 475
 		/* the same for FAILURE callbacks */
476 476
 		&& !has_tran_tmcbs( t, TMCB_ON_FAILURE_RO|TMCB_ON_FAILURE) 
477 477
 		/* something received -- we will not be silent on error */
Browse code

tm: Rename run_onsend_callbacks[2]; update, and extend documentation.

- run_onsend_callbacks -> run_trans_callbacks_with_buf.
- run_onsend_callbacks2 -> run_trans_callbacks_off_params.

Timo Reimann authored on 05/10/2011 08:57:13
Showing 1 changed files
... ...
@@ -393,8 +393,8 @@ inline static ticks_t retransmission_handler( struct retr_buf *r_buf )
393 393
 				return (ticks_t)-1;
394 394
 			}
395 395
 			if (unlikely(has_tran_tmcbs(r_buf->my_T, TMCB_REQUEST_SENT))) 
396
-				run_onsend_callbacks(TMCB_REQUEST_SENT, r_buf, 
397
-										0, 0, TMCB_RETR_F);
396
+				run_trans_callbacks_with_buf(TMCB_REQUEST_SENT, r_buf, 
397
+				0, 0, TMCB_RETR_F);
398 398
 	} else {
399 399
 #ifdef EXTRA_DEBUG
400 400
 			DBG("DEBUG: retransmission_handler : "
Browse code

tm: Always compile TMCB_ONSEND code, it was used unconditionally anyway.

Timo Reimann authored on 05/10/2011 08:14:21
Showing 1 changed files
... ...
@@ -392,11 +392,9 @@ inline static ticks_t retransmission_handler( struct retr_buf *r_buf )
392 392
 				fake_reply(r_buf->my_T, r_buf->branch, 503 );
393 393
 				return (ticks_t)-1;
394 394
 			}
395
-#ifdef TMCB_ONSEND
396 395
 			if (unlikely(has_tran_tmcbs(r_buf->my_T, TMCB_REQUEST_SENT))) 
397 396
 				run_onsend_callbacks(TMCB_REQUEST_SENT, r_buf, 
398 397
 										0, 0, TMCB_RETR_F);
399
-#endif
400 398
 	} else {
401 399
 #ifdef EXTRA_DEBUG
402 400
 			DBG("DEBUG: retransmission_handler : "
Browse code

tm: keep internal retr. intervals in ms

When using ticks to keep the retransmission intervals, any
rounding error (when converting from ms to ticks) is increased
with each doubling of the retransmission interval. In the standard
configuration this means that the last retransmission before t2
kicks in, has an error up to 4 times bigger then the initial one
(the rounding error is max. 1 tick/62.5ms for the initial interval
=> up to 250 ms for the last retransmission before t2).

By keeping the retransmission intervals in ms instead of ticks,
this problem is avoided, and the timing error is always < 1 tick
(62.5 ms) + system timer error (< 10 ms usually).

Andrei Pelinescu-Onciul authored on 11/08/2011 14:58:12
Showing 1 changed files
... ...
@@ -150,8 +150,8 @@
150 150
 struct msgid_var user_fr_timeout;
151 151
 struct msgid_var user_fr_inv_timeout;
152 152
 #ifdef TM_DIFF_RT_TIMEOUT
153
-struct msgid_var user_rt_t1_timeout;
154
-struct msgid_var user_rt_t2_timeout;
153
+struct msgid_var user_rt_t1_timeout_ms;
154
+struct msgid_var user_rt_t2_timeout_ms;
155 155
 #endif
156 156
 struct msgid_var user_inv_max_lifetime;
157 157
 struct msgid_var user_noninv_max_lifetime;
... ...
@@ -185,8 +185,6 @@ int tm_init_timers(void)
185 185
 	default_tm_cfg.fr_inv_timeout=MS_TO_TICKS(default_tm_cfg.fr_inv_timeout);
186 186
 	default_tm_cfg.wait_timeout=MS_TO_TICKS(default_tm_cfg.wait_timeout);
187 187
 	default_tm_cfg.delete_timeout=MS_TO_TICKS(default_tm_cfg.delete_timeout);
188
-	default_tm_cfg.rt_t1_timeout=MS_TO_TICKS(default_tm_cfg.rt_t1_timeout);
189
-	default_tm_cfg.rt_t2_timeout=MS_TO_TICKS(default_tm_cfg.rt_t2_timeout);
190 188
 	default_tm_cfg.tm_max_inv_lifetime=MS_TO_TICKS(default_tm_cfg.tm_max_inv_lifetime);
191 189
 	default_tm_cfg.tm_max_noninv_lifetime=MS_TO_TICKS(default_tm_cfg.tm_max_noninv_lifetime);
192 190
 	/* fix 0 values to 1 tick (minimum possible wait time ) */
... ...
@@ -194,8 +192,8 @@ int tm_init_timers(void)
194 192
 	if (default_tm_cfg.fr_inv_timeout==0) default_tm_cfg.fr_inv_timeout=1;
195 193
 	if (default_tm_cfg.wait_timeout==0) default_tm_cfg.wait_timeout=1;
196 194
 	if (default_tm_cfg.delete_timeout==0) default_tm_cfg.delete_timeout=1;
197
-	if (default_tm_cfg.rt_t2_timeout==0) default_tm_cfg.rt_t2_timeout=1;
198
-	if (default_tm_cfg.rt_t1_timeout==0) default_tm_cfg.rt_t1_timeout=1;
195
+	if (default_tm_cfg.rt_t2_timeout_ms==0) default_tm_cfg.rt_t2_timeout_ms=1;
196
+	if (default_tm_cfg.rt_t1_timeout_ms==0) default_tm_cfg.rt_t1_timeout_ms=1;
199 197
 	if (default_tm_cfg.tm_max_inv_lifetime==0) default_tm_cfg.tm_max_inv_lifetime=1;
200 198
 	if (default_tm_cfg.tm_max_noninv_lifetime==0) default_tm_cfg.tm_max_noninv_lifetime=1;
201 199
 	
... ...
@@ -203,8 +201,10 @@ int tm_init_timers(void)
203 201
 	SIZE_FIT_CHECK(fr_timeout, default_tm_cfg.fr_timeout, "fr_timer");
204 202
 	SIZE_FIT_CHECK(fr_inv_timeout, default_tm_cfg.fr_inv_timeout, "fr_inv_timer");
205 203
 #ifdef TM_DIFF_RT_TIMEOUT
206
-	SIZE_FIT_CHECK(rt_t1_timeout, default_tm_cfg.rt_t1_timeout, "retr_timer1");
207
-	SIZE_FIT_CHECK(rt_t2_timeout, default_tm_cfg.rt_t2_timeout, "retr_timer2");
204
+	SIZE_FIT_CHECK(rt_t1_timeout_ms, default_tm_cfg.rt_t1_timeout_ms,
205
+					"retr_timer1");
206
+	SIZE_FIT_CHECK(rt_t2_timeout_ms, default_tm_cfg.rt_t2_timeout_ms,
207
+					"retr_timer2");
208 208
 #endif
209 209
 	SIZE_FIT_CHECK(end_of_life, default_tm_cfg.tm_max_inv_lifetime, "max_inv_lifetime");
210 210
 	SIZE_FIT_CHECK(end_of_life, default_tm_cfg.tm_max_noninv_lifetime, "max_noninv_lifetime");
... ...
@@ -212,8 +212,8 @@ int tm_init_timers(void)
212 212
 	memset(&user_fr_timeout, 0, sizeof(user_fr_timeout));
213 213
 	memset(&user_fr_inv_timeout, 0, sizeof(user_fr_inv_timeout));
214 214
 #ifdef TM_DIFF_RT_TIMEOUT
215
-	memset(&user_rt_t1_timeout, 0, sizeof(user_rt_t1_timeout));
216
-	memset(&user_rt_t2_timeout, 0, sizeof(user_rt_t2_timeout));
215
+	memset(&user_rt_t1_timeout_ms, 0, sizeof(user_rt_t1_timeout_ms));
216
+	memset(&user_rt_t2_timeout_ms, 0, sizeof(user_rt_t2_timeout_ms));
217 217
 #endif
218 218
 	memset(&user_inv_max_lifetime, 0, sizeof(user_inv_max_lifetime));
219 219
 	memset(&user_noninv_max_lifetime, 0, sizeof(user_noninv_max_lifetime));
... ...
@@ -222,7 +222,7 @@ int tm_init_timers(void)
222 222
 			" max_inv_lifetime=%d max_noninv_lifetime=%d\n",
223 223
 			default_tm_cfg.fr_timeout, default_tm_cfg.fr_inv_timeout,
224 224
 			default_tm_cfg.wait_timeout, default_tm_cfg.delete_timeout,
225
-			default_tm_cfg.rt_t1_timeout, default_tm_cfg.rt_t2_timeout,
225
+			default_tm_cfg.rt_t1_timeout_ms, default_tm_cfg.rt_t2_timeout_ms,
226 226
 			default_tm_cfg.tm_max_inv_lifetime, default_tm_cfg.tm_max_noninv_lifetime);
227 227
 	return 0;
228 228
 error:
... ...
@@ -263,10 +263,6 @@ int timer_fixup(void *handle, str *gname, str *name, void **val)
263 263
 	/* size fix checks */
264 264
 	IF_IS_TIMER_NAME(fr_timeout, "fr_timer")
265 265
 	else IF_IS_TIMER_NAME(fr_inv_timeout, "fr_inv_timer")
266
-#ifdef TM_DIFF_RT_TIMEOUT
267
-	else IF_IS_TIMER_NAME(rt_t1_timeout, "retr_timer1")
268
-	else IF_IS_TIMER_NAME(rt_t2_timeout, "retr_timer2")
269
-#endif
270 266
 	else IF_IS_TIMER_NAME(end_of_life, "max_inv_lifetime")
271 267
 	else IF_IS_TIMER_NAME(end_of_life, "max_noninv_lifetime")
272 268
 
... ...
@@ -277,6 +273,30 @@ error:
277 273
 	return -1;
278 274
 }
279 275
 
276
+
277
+
278
+/** fixup function for timer values that are kept in ms.
279
+ * (called by the configuration framework)
280
+ * It checks if the value fits in the tm structures 
281
+ */
282
+int timer_fixup_ms(void *handle, str *gname, str *name, void **val)
283
+{
284
+	long	t;
285
+
286
+	t = (long)(*val);
287
+
288
+	/* size fix checks */
289
+#ifdef TM_DIFF_RT_TIMEOUT
290
+	IF_IS_TIMER_NAME(rt_t1_timeout_ms, "retr_timer1")
291
+	else IF_IS_TIMER_NAME(rt_t2_timeout_ms, "retr_timer2")
292
+#endif
293
+
294
+	return 0;
295
+
296
+error:
297
+	return -1;
298
+}
299
+
280 300
 /******************** handlers ***************************/
281 301