Browse code

ref_count turned into ref_bitmap; oncancel module handler added

Jiri Kuthan authored on 11/01/2002 19:58:58
Showing 13 changed files
... ...
@@ -385,6 +385,7 @@ int run_actions(struct action* a, struct sip_msg* msg)
385 385
 	struct action* t;
386 386
 	int ret;
387 387
 	static int rec_lev=0;
388
+	struct sr_module *mod;
388 389
 
389 390
 	rec_lev++;
390 391
 	if (rec_lev>ROUTE_MAX_REC_LEV){
... ...
@@ -408,6 +409,13 @@ int run_actions(struct action* a, struct sip_msg* msg)
408 408
 	}
409 409
 	
410 410
 	rec_lev--;
411
+	/* process module onbreak handlers if present */
412
+	if (rec_lev==0 && ret==0) 
413
+		for (mod=modules;mod;mod=mod->next) 
414
+			if (mod->exports && mod->exports->onbreak_f) {
415
+				mod->exports->onbreak_f( msg );
416
+				DBG("DEBUG: %s onbreak handler called\n", mod->exports->name);
417
+			}
411 418
 	return ret;
412 419
 	
413 420
 
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  $Id $
2
+ *  $Id$
3 3
  */
4 4
 
5 5
 
... ...
@@ -7,6 +7,8 @@
7 7
 #ifndef config_h
8 8
 #define config_h
9 9
 
10
+#include "types.h"
11
+
10 12
 /* default sip port if none specified */
11 13
 #define SIP_PORT 5060
12 14
 
... ...
@@ -62,12 +64,17 @@
62 62
 #define MAX_BUCKET		15
63 63
 
64 64
 /* receive buffer size -- preferably set low to
65
-   avoid terror of excessively huge messages
65
+   avoid terror of excessively huge messages; they are
66
+   useless anyway
66 67
 */
67 68
 #define BUF_SIZE (MAX_FIXED_BLOCK-32)
68 69
 
69
-/* forwarding */
70
+/* forwarding  -- Via buffer dimensioning */
70 71
 #define MAX_VIA_LINE_SIZE	240
71 72
 #define MAX_RECEIVED_SIZE	57
72 73
 
74
+/* maximum number of processes is constrained by capacity of
75
+   process bitmaps */
76
+#define MAX_PROCESSES (sizeof( process_bm_t) * 8 )
77
+
73 78
 #endif
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- * $Id*
2
+ * $Id$
3 3
  *
4 4
  * global variables
5 5
  *
... ...
@@ -9,6 +9,8 @@
9 9
 #ifndef globals_h
10 10
 #define globals_h
11 11
 
12
+#include "types.h"
13
+
12 14
 #define NO_DNS     0
13 15
 #define DO_DNS     1
14 16
 #define DO_REV_DNS 2
... ...
@@ -32,6 +34,8 @@ extern int check_via;
32 32
 extern int received_dns;
33 33
 extern int loop_checks;
34 34
 extern int process_no;
35
+
36
+extern process_bm_t process_bit;
35 37
 extern int *pids;
36 38
 
37 39
 extern int cfg_errors;
... ...
@@ -118,8 +118,8 @@ Options:\n\
118 118
 /* print compile-time constants */
119 119
 void print_ct_constants()
120 120
 {
121
-	printf("MAX_RECV_BUFFER_SIZE %d, MAX_LISTEN %d, MAX_URI_SIZE %d\n",
122
-		MAX_RECV_BUFFER_SIZE, MAX_LISTEN, MAX_URI_SIZE );
121
+	printf("MAX_RECV_BUFFER_SIZE %d, MAX_LISTEN %d, MAX_URI_SIZE %d, MAX_PROCESSES %d\n",
122
+		MAX_RECV_BUFFER_SIZE, MAX_LISTEN, MAX_URI_SIZE, MAX_PROCESSES );
123 123
 }
124 124
 
125 125
 /* debuging function */
... ...
@@ -166,6 +166,7 @@ int addresses_no=0;                    /* number of names/ips */
166 166
 
167 167
 /* ipc related globals */
168 168
 int process_no = 0;
169
+process_bm_t process_bit = 0;
169 170
 #ifdef ROUTE_SRV
170 171
 #endif
171 172
 
... ...
@@ -261,6 +262,7 @@ int main_loop()
261 261
 				if (pid==0){
262 262
 					/* child */
263 263
 					/* timer!*/
264
+					process_bit = 0;
264 265
 					for(;;){
265 266
 						sleep(TIMER_TICK);
266 267
 						timer_ticker();
... ...
@@ -272,6 +274,7 @@ int main_loop()
272 272
 		/* main process, receive loop */
273 273
 		is_main=1;
274 274
 		pids[0]=getpid();
275
+		process_bit = 1;
275 276
 		process_no=0; /*main process number*/
276 277
 		udp_rcv_loop();
277 278
 	}else{
... ...
@@ -286,6 +289,7 @@ int main_loop()
286 286
 				if (pid==0){
287 287
 					/* child */
288 288
 					process_no=i+1; /*0=main*/
289
+					process_bit = 1 << i;
289 290
 #ifdef STATS
290 291
 					setstats( i );
291 292
 #endif
... ...
@@ -299,6 +303,7 @@ int main_loop()
299 299
 	}
300 300
 	/*this is the main process*/
301 301
 	pids[process_no]=getpid();
302
+	process_bit = 0;
302 303
 	is_main=1;
303 304
 	if (timer_list){
304 305
 		for(;;){
... ...
@@ -569,6 +574,11 @@ int main(int argc, char** argv)
569 569
 
570 570
 	
571 571
 	if (children_no<=0) children_no=CHILD_NO;
572
+	else if (children_no >= MAX_PROCESSES ) {
573
+		fprintf(stderr, "ERROR: too many children processes configured; maximum is %d\n",
574
+			MAX_PROCESSES-1 );
575
+		goto error;
576
+	}
572 577
 	/*alloc pids*/
573 578
 #ifdef SHM_MEM
574 579
 	pids=shm_malloc(sizeof(int)*children_no);
... ...
@@ -31,17 +31,15 @@ void free_cell( struct cell* dead_cell )
31 31
 		/* outbound requests*/
32 32
 		DBG("DEBUG: free_cell: outbound_request[%d] %p\n",i,dead_cell->outbound_request[i]);
33 33
 		if ( rb=dead_cell->outbound_request[i] )
34
-      		{
35
-/*
36
-			if (rb->retr_buffer) shm_free( rb->retr_buffer );
34
+   		{
35
+			if (rb->retr_buffer) shm_free_unsafe( rb->retr_buffer );
37 36
 	 		dead_cell->outbound_request[i] = NULL;
38
-*/
39 37
          		shm_free_unsafe( rb );
40
-      		}
41
-      		/* outbound requests*/
42
-      		DBG("DEBUG: free_cell: inbound_response[%d] %p\n",i,dead_cell->inbound_response[i]);
43
-      		if ( dead_cell -> inbound_response[i] )
44
-         		sip_msg_free_unsafe( dead_cell->inbound_response[i] );
38
+   		}
39
+   		/* outbound requests*/
40
+   		DBG("DEBUG: free_cell: inbound_response[%d] %p\n",i,dead_cell->inbound_response[i]);
41
+   		if ( dead_cell -> inbound_response[i] )
42
+       		sip_msg_free_unsafe( dead_cell->inbound_response[i] );
45 43
    	}
46 44
    	/* mutex */
47 45
    	/* release_cell_lock( dead_cell ); */
... ...
@@ -12,6 +12,7 @@
12 12
 #include <arpa/inet.h>
13 13
 
14 14
 #include "../../msg_parser.h"
15
+#include "../../types.h"
15 16
 #include "config.h"
16 17
 
17 18
 struct s_table;
... ...
@@ -37,18 +38,11 @@ typedef struct retrans_buff
37 37
    int                  bufflen;
38 38
 
39 39
    struct sockaddr_in to;
40
-   /* changed in favour of Solaris to size_t
41
-   socklen_t tolen;
42
-   */
43 40
    size_t tolen;
44 41
 
45 42
    /* a message can be linked just to retransmission and FR list */
46 43
    struct timer_link retr_timer;
47 44
    struct timer_link fr_timer;
48
-/*
49
-   unsigned int timeout_ceiling;
50
-   unsigned int timeout_value;
51
-*/
52 45
 
53 46
    /*the cell that containes this retrans_buff*/
54 47
    struct cell* my_T;
... ...
@@ -62,43 +56,38 @@ typedef struct retrans_buff
62 62
 
63 63
 typedef struct cell
64 64
 {
65
-   /* linking data */
66
-   struct cell*     next_cell;
67
-   struct cell*     prev_cell;
68
-
69
-   /*sync data */
70
-   /*
71
-	/* we use hash table mutexes now */
72
-   /* ser_lock_t   mutex; */
73
-   int       ref_counter;
74
-
75
-   /* cell payload data */
76
-   /* tells in which hash table entry the cell lives */
77
-   unsigned int  hash_index;
78
-   /* sequence number within hash collision slot */
79
-   unsigned int  label;
80
-
81
-   /* bindings to wait and delete timer */
82
-   struct timer_link wait_tl;
83
-   struct timer_link dele_tl;
84
-
85
-   /*the transaction that is canceled (usefull only for CANCEL req)*/
86
-   struct cell *T_canceled;
87
-   struct cell *T_canceler;
88
-
89
-   /* usefull data */
90
-   /* UA Server */
91
-   struct sip_msg         *inbound_request;
92
-   struct retrans_buff   outbound_response;
93
-   unsigned int             status;
94
-   str*                             tag;
95
-   unsigned int             inbound_request_isACKed;
96
-   int                              relaied_reply_branch;
97
-   int                               nr_of_outgoings;
98
-   /* UA Clients */
99
-   struct retrans_buff   *outbound_request[ MAX_FORK ];
100
-   struct sip_msg          *inbound_response[ MAX_FORK ];
101
-   unsigned int             outbound_request_isACKed[MAX_FORK];
65
+	/* linking data */
66
+	struct cell*     next_cell;
67
+	struct cell*     prev_cell;
68
+
69
+	/* indicates which process is currently processing this transaction */
70
+	process_bm_t	ref_bitmap;
71
+	/* tells in which hash table entry the cell lives */
72
+	unsigned int  hash_index;
73
+	/* sequence number within hash collision slot */
74
+	unsigned int  label;
75
+
76
+	/* bindings to wait and delete timer */
77
+	struct timer_link wait_tl;
78
+	struct timer_link dele_tl;
79
+
80
+	/*the transaction that is canceled (usefull only for CANCEL req)*/
81
+	struct cell *T_canceled;
82
+	struct cell *T_canceler;
83
+
84
+	/* useful data */
85
+	/* UA Server */
86
+	struct sip_msg         *inbound_request;
87
+	struct retrans_buff   outbound_response;
88
+	unsigned int             status;
89
+	str*                             tag;
90
+	unsigned int             inbound_request_isACKed;
91
+	int                              relaied_reply_branch;
92
+	int                               nr_of_outgoings;
93
+	/* UA Clients */
94
+	struct retrans_buff   *outbound_request[ MAX_FORK ];
95
+	struct sip_msg          *inbound_response[ MAX_FORK ];
96
+	unsigned int             outbound_request_isACKed[MAX_FORK];
102 97
 
103 98
 #ifdef	EXTRA_DEBUG
104 99
 	/* scheduled for deletion ? */
... ...
@@ -174,7 +174,7 @@ int t_add_transaction( struct sip_msg* p_msg, char* foo, char* bar )
174 174
    DBG("DEBUG: t_add_transaction: new transaction inserted, hash: %d\n", new_cell->hash_index );
175 175
 
176 176
    T = new_cell;
177
-   T->ref_counter =1;
177
+	T_REF(T);
178 178
    return 1;
179 179
 }
180 180
 
... ...
@@ -451,7 +451,8 @@ int t_on_reply_received( struct sip_msg  *p_msg )
451 451
 	msg_class=REPLY_CLASS(p_msg);
452 452
 	relay = t_should_relay_response( T , msg_status );
453 453
 	if (relay && !(clone=sip_msg_cloner( p_msg ))) {
454
-		t_unref( p_msg, NULL, NULL );
454
+		T_UNREF( T );
455
+		/* t_unref( p_msg, NULL, NULL ); */
455 456
 		return 0;
456 457
 	}
457 458
 
... ...
@@ -481,7 +482,8 @@ int t_on_reply_received( struct sip_msg  *p_msg )
481 481
            		{
482 482
                			LOG( L_ERR , "ERROR: t_on_reply_received: unable to send ACK\n" );
483 483
 						if (clone ) sip_msg_free( clone );
484
-						t_unref( p_msg, NULL, NULL );
484
+						/* t_unref( p_msg, NULL, NULL ); */
485
+						T_UNREF( T );
485 486
                			return 0;
486 487
            		}
487 488
        		}
... ...
@@ -493,7 +495,8 @@ int t_on_reply_received( struct sip_msg  *p_msg )
493 493
 
494 494
 	/* if the incoming response code is not reliable->drop it*/
495 495
 	if (!relay) {
496
-		t_unref( p_msg, NULL, NULL );
496
+		/* t_unref( p_msg, NULL, NULL ); */
497
+		T_UNREF( T );
497 498
 		return 0;
498 499
 	}
499 500
 
... ...
@@ -522,11 +525,13 @@ int t_on_reply_received( struct sip_msg  *p_msg )
522 522
    	}
523 523
 
524 524
 	/* nothing to do for the ser core */
525
-	t_unref( p_msg, NULL, NULL );
525
+	/* t_unref( p_msg, NULL, NULL ); */
526
+	T_UNREF( T );
526 527
 	return 0;
527 528
 
528 529
 error:
529
-	t_unref( p_msg, NULL, NULL );
530
+	/* t_unref( p_msg, NULL, NULL ); */
531
+	T_UNREF( T );
530 532
 	T->inbound_response[branch]=NULL;
531 533
 	sip_msg_free( clone );
532 534
 	/* don't try to relay statelessly on error */
... ...
@@ -577,7 +582,7 @@ int t_unref( struct sip_msg* p_msg, char* foo, char* bar )
577 577
 {
578 578
 	if (T==T_UNDEFINED || T==T_NULL)
579 579
 		return -1;
580
-	unref_T(T);
580
+	T_UNREF( T );
581 581
 	T=T_UNDEFINED;
582 582
 	return 1;
583 583
 }
... ...
@@ -1091,16 +1096,16 @@ void delete_cell( struct cell *p_cell )
1091 1091
 	}
1092 1092
 #endif
1093 1093
 	/* still in use ... don't delete */
1094
-	if ( p_cell->ref_counter ) {
1094
+	if ( T_IS_REFED(p_cell) ) {
1095 1095
 #ifdef	EXTRA_DEBUG
1096
-		if (p_cell->ref_counter>1) {
1096
+		if (T_REFCOUNTER(p_cell)>1) {
1097 1097
 			DBG("DEBUG: while debugging with a single process, ref_count > 1\n");
1098 1098
 			DBG("DEBUG: transaction =%p\n", p_cell );
1099 1099
 			abort();
1100 1100
 		}
1101 1101
 #endif
1102
-		DBG("DEBUG: delete_cell: t=%p post for delete (%d)\n",
1103
-			p_cell,p_cell->ref_counter);
1102
+		DBG("DEBUG: delete_cell: t=%p post for delete (refbitmap %x, refcount %d)\n",
1103
+			p_cell,p_cell->ref_bitmap, T_REFCOUNTER(p_cell));
1104 1104
 		/* it's added to del list for future del */
1105 1105
 		set_timer( hash_table, &(p_cell->dele_tl), DELETE_LIST );
1106 1106
 	} else {
... ...
@@ -46,13 +46,54 @@ extern struct s_table*  hash_table;
46 46
 	__FUNCTION__, __LINE__ ); })
47 47
 
48 48
 
49
-/* to avoid too many locks/unlocks, we gave up using separate locks
50
-   for cells and use those of transaction table entries
49
+/* 
50
+  macros for reference bitmap (lock-less process non-exclusive ownership) 
51 51
 */
52
+#define T_IS_REFED(_T_cell) ((_T_cell)->ref_bitmap)
53
+#define T_REFCOUNTER(_T_cell) \
54
+	( { int _i=0; \
55
+		process_bm_t _b=(_T_cell)->ref_bitmap; \
56
+		while (_b) { \
57
+			if ( (_b) & 1 ) _i++; \
58
+			(_b) >>= 1; \
59
+		} ;\
60
+		(_i); \
61
+	 } )
62
+		
63
+
64
+#ifdef EXTRA_DEBUG
65
+#	define DBG_REF(_action, _t) DBG("DEBUG: XXXXX %s (%s:%d): T=%p , ref (bm=%x, cnt=%d)\n",\
66
+			(_action), __FUNCTION__, __LINE__, (_t),(_t)->ref_bitmap, T_REFCOUNTER(_t));
67
+#	define T_UNREF(_T_cell) \
68
+	( { \
69
+		DBG_REF("unref", (_T_cell)); \
70
+		if (!T_IS_REFED(_T_cell)) { \
71
+			DBG("ERROR: unrefering unrefered transaction %p from %s , %s : %d\n", \
72
+				(_T_cell), __FUNCTION__, __FILE__, __LINE__ ); \
73
+			abort(); \
74
+		} \
75
+		(_T_cell)->ref_bitmap &= ~process_bit; \
76
+	} )
77
+
78
+#	define T_REF(_T_cell) \
79
+	( { \
80
+		DBG_REF("ref", (_T_cell));	 \
81
+		if (T_IS_REFED(_T_cell)) { \
82
+			DBG("ERROR: refering already refered transaction %p from %s , %s : %d\n", \
83
+				(_T_cell), __FUNCTION__, __FILE__, __LINE__ ); \
84
+			abort(); \
85
+		} \
86
+		(_T_cell)->ref_bitmap |= process_bit; \
87
+	} )
88
+#else
89
+#	define T_UNREF(_T_cell) ({ (_T_cell)->ref_bitmap &= ~process_bit; })
90
+#	define T_REF(_T_cell) ({ (_T_cell)->ref_bitmap |= process_bit; })
91
+#endif
52 92
 
53
-#define DBG_REF(_action, _t) DBG("DEBUG: XXXXX %s (%s:%d): T=%p , ref=%d\n",\
54
-			(_action), __FUNCTION__, __LINE__, (_t),(_t)->ref_counter);
55 93
 
94
+	
95
+
96
+#ifdef _OLD_XX
56 97
 #define unref_T(_T_cell) \
57 98
 	( {\
58 99
 		lock( hash_table->entrys[(_T_cell)->hash_index].mutex );\
... ...
@@ -67,6 +108,7 @@ extern struct s_table*  hash_table;
67 67
 */
68 68
 #define ref_T(_T_cell) ({ ((_T_cell)->ref_counter++); \
69 69
 		DBG_REF("ref", (_T_cell));	})
70
+#endif
70 71
 
71 72
 
72 73
 int   tm_startup();
... ...
@@ -130,9 +130,10 @@ int t_lookup_request( struct sip_msg* p_msg )
130 130
 
131 131
 found:
132 132
 	T=p_cell;
133
-	ref_T( T );
133
+	/* ref_T( T ); */
134
+	T_REF( T );
134 135
 	DBG("DEBUG:XXXXXXXXXXXXXXXXXXXXX t_lookup_request: "
135
-			"transaction found ( T=%p , ref=%d)\n",T,T->ref_counter);
136
+			"transaction found ( T=%p , ref=%x)\n",T,T->ref_bitmap);
136 137
 	unlock( hash_table->entrys[hash_index].mutex );
137 138
 	return 1;
138 139
 }
... ...
@@ -285,9 +286,10 @@ int t_reply_matching( struct sip_msg *p_msg , unsigned int *p_branch )
285 285
           T = p_cell;
286 286
           *p_branch = branch_id;
287 287
           /* T->ref_counter ++; */
288
-		  ref_T( T );
288
+		  /* ref_T( T ); */
289
+			T_REF( T );
289 290
           unlock( hash_table->entrys[hash_index].mutex );
290
-          DBG("DEBUG:XXXXXXXXXXXXXXXXXXXXX t_reply_matching: reply matched (T=%p, ref=%d)!\n",T,T->ref_counter);
291
+          DBG("DEBUG:XXXXXXXXXXXXXXXXXXXXX t_reply_matching: reply matched (T=%p, ref=%x)!\n",T,T->ref_bitmap);
291 292
         return 1;
292 293
       }
293 294
       /* next cell */
... ...
@@ -324,8 +326,10 @@ int t_check( struct sip_msg* p_msg , int *param_branch)
324 324
    if ( p_msg->id != global_msg_id || T==T_UNDEFINED )
325 325
    {
326 326
       global_msg_id = p_msg->id;
327
+	/*
327 328
       if ( T && T!=T_UNDEFINED )
328 329
          unref_T(T);
330
+	*/
329 331
       T = T_UNDEFINED;
330 332
       /* transaction lookup */
331 333
      if ( p_msg->first_line.type==SIP_REQUEST ) {
... ...
@@ -30,6 +30,8 @@ static int fixup_t_forward(void** param, int param_no);
30 30
 static int fixup_t_forward_def(void** param, int param_no);
31 31
 static int fixup_t_send_reply(void** param, int param_no);
32 32
 
33
+static void w_onbreak(struct sip_msg* msg) { t_unref(msg, NULL, NULL); }
34
+
33 35
 static struct module_exports nm_exports= {
34 36
 	"tm_module",
35 37
 	(char*[]){			"t_add_transaction",
... ...
@@ -77,7 +79,8 @@ static struct module_exports nm_exports= {
77 77
 		},
78 78
 	9,
79 79
 	(response_function) t_on_reply_received,
80
-	(destroy_function) tm_shutdown
80
+	(destroy_function) tm_shutdown,
81
+	w_onbreak
81 82
 };
82 83
 
83 84
 
... ...
@@ -12,6 +12,7 @@ typedef  struct module_exports* (*module_register)();
12 12
 typedef  int (*cmd_function)(struct sip_msg*, char*, char*);
13 13
 typedef  int (*fixup_function)(void** param, int param_no);
14 14
 typedef  int (*response_function)(struct sip_msg*);
15
+typedef  void (*onbreak_function)(struct sip_msg*);
15 16
 typedef void (*destroy_function)();
16 17
 
17 18
 struct module_exports{
... ...
@@ -29,6 +30,7 @@ struct module_exports{
29 29
 	destroy_function destroy_f; /*function called when the module should
30 30
 								  be "destroyed", e.g: on ser exit;
31 31
 								  can be null */
32
+	onbreak_function onbreak_f;
32 33
 };
33 34
 
34 35
 struct sr_module{
... ...
@@ -9,7 +9,9 @@ log_stderror=yes # (cmd line: -E)
9 9
 check_via=yes     # (cmd. line: -v)
10 10
 dns=on           # (cmd. line: -r)
11 11
 rev_dns=yes      # (cmd. line: -R)
12
-fork=no          # (cmd. line: -D)
12
+fork=yes
13
+children=4
14
+#fork=no          # (cmd. line: -D)
13 15
 port=5080
14 16
 #listen=127.0.0.1
15 17
 listen=192.168.99.100
... ...
@@ -47,6 +49,7 @@ route[0]{
47 47
 			};
48 48
 #			t_forward("195.37.77.100", "5090" );
49 49
 			t_forward("195.37.78.146", "5060" );
50
+			break;
50 51
 			t_unref();
51 52
 		};
52 53
 	};
53 54
new file mode 100644
... ...
@@ -0,0 +1,11 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ */
4
+
5
+#ifndef _TYPES_H_
6
+#define _TYPES_H_
7
+
8
+typedef unsigned int process_bm_t;
9
+
10
+#endif