Browse code

memory access syncing protection added

Jiri Kuthan authored on 28/01/2002 23:30:56
Showing 16 changed files
... ...
@@ -53,7 +53,7 @@ ARCH = $(shell uname -s)
53 53
 
54 54
 DEFS+= -DNAME='"$(NAME)"' -DVERSION='"$(RELEASE)"' -DARCH='"$(ARCH)"' \
55 55
 	 -DDNS_IP_HACK  -DPKG_MALLOC -DSHM_MEM  -DSHM_MMAP \
56
-	 -DVQ_MALLOC 
56
+	-DVQ_MALLOC -DBRUT_HACK #-DEXTRA_DEBUG #-DSTATIC_TM #-DEXTRA_DEBUG
57 57
 	#-DEXTRA_DEBUG -DBRUT_HACK \
58 58
 	#-DVQ_MALLOC  -DDBG_LOCK  #-DSTATS
59 59
 	  #-DDBG_QM_MALLOC #-DVQ_MALLOC #-DNO_DEBUG
... ...
@@ -7,7 +7,7 @@
7 7
 #define _TM_CONFIG_H
8 8
 
9 9
 /* always use a power of 2 for hash table size */
10
-#define T_TABLE_POWER		10
10
+#define T_TABLE_POWER		12
11 11
 #define TABLE_ENTRIES  		(2 << (T_TABLE_POWER-1))
12 12
 
13 13
 /* maximum number of forks per transaction */
... ...
@@ -7,7 +7,6 @@
7 7
 #include "../../dprint.h"
8 8
 #include "sh_malloc.h"
9 9
 
10
-
11 10
 /*   Frees the all the containes of a cell and the cell's body itself
12 11
   */
13 12
 void free_cell( struct cell* dead_cell )
... ...
@@ -19,6 +18,7 @@ void free_cell( struct cell* dead_cell )
19 19
 	DBG("DEBUG: free_cell: start\n");
20 20
 	/* UA Server */
21 21
 	DBG("DEBUG: free_cell: inbound request %p\n",dead_cell->inbound_request);
22
+	release_cell_lock( dead_cell );
22 23
 	shm_lock();
23 24
 	if ( dead_cell->inbound_request )
24 25
 		sip_msg_free_unsafe( dead_cell->inbound_request );
... ...
@@ -36,6 +36,9 @@ void free_cell( struct cell* dead_cell )
36 36
 	 		dead_cell->outbound_request[i] = NULL;
37 37
          		shm_free_unsafe( rb );
38 38
    		}
39
+		/* outbound ACKs, if any */
40
+		if (rb=dead_cell->outbound_ack[i] )
41
+			shm_free_unsafe( rb );
39 42
    		/* outbound requests*/
40 43
    		DBG("DEBUG: free_cell: inbound_response[%d] %p\n",i,dead_cell->inbound_response[i]);
41 44
    		if ( dead_cell -> inbound_response[i] )
... ...
@@ -141,8 +144,15 @@ struct cell*  build_cell( struct sip_msg* p_msg )
141 141
 
142 142
    /* filling with 0 */
143 143
    memset( new_cell, 0, sizeof( struct cell ) );
144
+
145
+	new_cell->outbound_response.retr_timer.tg=TG_RT;
146
+	new_cell->outbound_response.fr_timer.tg=TG_FR;
147
+	new_cell->wait_tl.tg=TG_WT;
148
+	new_cell->dele_tl.tg=TG_DEL;
149
+
144 150
    /* hash index of the entry */
145
-   new_cell->hash_index = hash( p_msg->callid->body , get_cseq(p_msg)->number );
151
+   /* new_cell->hash_index = hash( p_msg->callid->body , get_cseq(p_msg)->number ); */
152
+	new_cell->hash_index = p_msg->hash_index;
146 153
    /* mutex */
147 154
    /* ref counter is 0 */
148 155
    /* all pointers from timers list tl are NULL */
... ...
@@ -153,19 +163,10 @@ struct cell*  build_cell( struct sip_msg* p_msg )
153 153
    DBG("DEBUG: build_cell : clone done\n");
154 154
    if (!new_cell->inbound_request)
155 155
 	goto error;
156
-   /* inbound response is NULL*/
157
-   /* status is 0 */
158
-   /* tag pointer is NULL */
159
-   //if ( p_msg->tag )      TO DO !!!!!!!!!!!!!!!!!!!!!!
160
-   //   new_cell->tag  =  &(new_cell->inbound_request->tag->body);
161
-   /* nr of outbound requests is 0 */
162
-   /* all pointers from outbound_request array are NULL */
163
-   /* all pointers from outbound_response array are NULL */
164
-   /*init the links with the canceled / canceler transaction */
165 156
    new_cell->relaied_reply_branch   = -1;
166 157
    new_cell->T_canceled = T_UNDEFINED;
167 158
 
168
-   /* init_cell_lock(  new_cell ); */
159
+    init_cell_lock(  new_cell ); 
169 160
 
170 161
    DBG("DEBUG: build_cell : done\n");
171 162
    return new_cell;
... ...
@@ -181,31 +182,28 @@ error:
181 181
 /*  Takes an already created cell and links it into hash table on the
182 182
   *  appropiate entry.
183 183
   */
184
-void    insert_into_hash_table( struct s_table *hash_table,  struct cell * p_cell )
184
+void    insert_into_hash_table_unsafe( struct s_table *hash_table,  struct cell * p_cell )
185 185
 {
186
-   struct entry* p_entry;
187
-
188
-   /* do we have or not something to insert? */
189
-   if (!p_cell)
190
-      return;
186
+	struct entry* p_entry;
191 187
 
192
-   /* locates the apropiate entry */
193
-   p_entry = &hash_table->entrys[ p_cell->hash_index ];
188
+	/* locates the apropiate entry */
189
+	p_entry = &hash_table->entrys[ p_cell->hash_index ];
194 190
 
195
-   /* critical region - inserting the cell at the end of the list */
196
-   lock( p_entry->mutex );
197
-
198
-   p_cell->label = p_entry->next_label++;
199
-   if ( p_entry->last_cell )
200
-   {
201
-      p_entry->last_cell->next_cell = p_cell;
202
-      p_cell->prev_cell = p_entry->last_cell;
203
-   }
204
-   else
205
-      p_entry->first_cell = p_cell;
206
-   p_entry->last_cell = p_cell;
191
+	p_cell->label = p_entry->next_label++;
192
+	if ( p_entry->last_cell )
193
+	{
194
+		p_entry->last_cell->next_cell = p_cell;
195
+		p_cell->prev_cell = p_entry->last_cell;
196
+	} else p_entry->first_cell = p_cell;
197
+	
198
+	p_entry->last_cell = p_cell;
199
+}
207 200
 
208
-   unlock( p_entry->mutex );
201
+void insert_into_hash_table( struct s_table *hash_table,  struct cell * p_cell )
202
+{
203
+	lock( hash_table->entrys[ p_cell->hash_index ].mutex );
204
+	insert_into_hash_table_unsafe( hash_table,  p_cell );
205
+	unlock( hash_table->entrys[ p_cell->hash_index ].mutex );
209 206
 }
210 207
 
211 208
 
... ...
@@ -34,20 +34,22 @@ struct timer;
34 34
 
35 35
 typedef struct retrans_buff
36 36
 {
37
-   char               *retr_buffer;
38
-   int                  bufflen;
37
+	char               *retr_buffer;
38
+	int                  bufflen;
39 39
 
40
-   struct sockaddr_in to;
41
-   size_t tolen;
40
+	struct sockaddr_in to;
41
+	size_t tolen;
42 42
 
43
-   /* a message can be linked just to retransmission and FR list */
44
-   struct timer_link retr_timer;
45
-   struct timer_link fr_timer;
43
+	/* a message can be linked just to retransmission and FR list */
44
+	struct timer_link retr_timer;
45
+	struct timer_link fr_timer;
46 46
 
47
-   /*the cell that containes this retrans_buff*/
48
-   struct cell* my_T;
47
+	/*the cell that containes this retrans_buff*/
48
+	struct cell* my_T;
49 49
 
50 50
 	enum lists retr_list;
51
+	/* set to status code if the buffer is a reply, 0 if request */
52
+	int reply;
51 53
 
52 54
 }retrans_buff_type;
53 55
 
... ...
@@ -76,17 +78,28 @@ typedef struct cell
76 76
 
77 77
 	/* useful data */
78 78
 	/* UA Server */
79
-	struct sip_msg         *inbound_request;
80
-	struct retrans_buff   outbound_response;
81
-	unsigned int             status;
82
-	str*                             tag;
83
-	unsigned int             inbound_request_isACKed;
84
-	int                              relaied_reply_branch;
85
-	int                               nr_of_outgoings;
79
+	struct sip_msg 		*inbound_request;
80
+	struct retrans_buff	outbound_response;
81
+	unsigned int		status;
82
+	str*				tag;
83
+	unsigned int		inbound_request_isACKed;
84
+	int					relaied_reply_branch;
85
+	int					nr_of_outgoings;
86 86
 	/* UA Clients */
87
-	struct retrans_buff   *outbound_request[ MAX_FORK ];
88
-	struct sip_msg          *inbound_response[ MAX_FORK ];
89
-	unsigned int             outbound_request_isACKed[MAX_FORK];
87
+	struct retrans_buff	*outbound_request[ MAX_FORK ];
88
+	struct sip_msg		*inbound_response[ MAX_FORK ];
89
+	/* unsigned int		outbound_request_isACKed[MAX_FORK]; */
90
+	struct retrans_buff	*outbound_ack[ MAX_FORK ];
91
+
92
+	/* protection against concurrent reply processing */
93
+	ser_lock_t	reply_mutex;
94
+	/* protection against concurrent ACK processing */
95
+	ser_lock_t	ack_mutex;
96
+
97
+	/* this is where destination is stored for picked branch;
98
+	   good if a need to forward ACK later on
99
+	*/
100
+	struct sockaddr_in ack_to;
90 101
 
91 102
 #ifdef	EXTRA_DEBUG
92 103
 	/* scheduled for deletion ? */
... ...
@@ -125,5 +138,6 @@ void free_cell( struct cell* dead_cell );
125 125
 struct cell*  build_cell( struct sip_msg* p_msg );
126 126
 void remove_from_hash_table( struct s_table *hash_table, struct cell * p_cell );
127 127
 void insert_into_hash_table( struct s_table *hash_table, struct cell * p_cell );
128
+void insert_into_hash_table_unsafe( struct s_table *hash_table, struct cell * p_cell );
128 129
 
129 130
 #endif
... ...
@@ -39,9 +39,17 @@
39 39
 */
40 40
 
41 41
 /* keep the semaphore here */
42
-int entry_semaphore=0, transaction_timer_semaphore=0, retrasmission_timer_semaphore=0;
43
-/* and the number of semaphores in the entry_semaphore set */
44
-int sem_nr;
42
+static int
43
+	entry_semaphore=0, 
44
+	timer_semaphore=0, 
45
+	reply_semaphore=0,
46
+	ack_semaphore=0;
47
+/* and the maximum number of semaphores in the entry_semaphore set */
48
+static int sem_nr;
49
+/* timer group locks */
50
+
51
+ser_lock_t timer_group_lock[TG_NR];
52
+
45 53
 
46 54
 
47 55
 /* intitialize the locks; return 0 on success, -1 otherwise
... ...
@@ -57,16 +65,16 @@ int lock_initialize()
57 57
 	DBG("DEBUG: lock_initialize: lock initialization started\n");
58 58
 
59 59
 	/* transaction timers */
60
-	if ((transaction_timer_semaphore=init_semaphore_set( NR_OF_TIMER_LISTS) ) < 0) {
61
-                LOG(L_ERR, "ERROR: lock_initialize:  transaction timer semaphore initialization failure\n");
60
+	if ((timer_semaphore= init_semaphore_set( TG_NR ) ) < 0) {
61
+                LOG(L_ERR, "ERROR: lock_initialize:  "
62
+			"transaction timer semaphore initialization failure\n");
62 63
 		goto error;
63 64
 	}
64 65
 
65
-	/* message retransmission timers
66
-        if ((retrasmission_timer_semaphore=init_semaphore_set( NR_OF_RT_LISTS) ) < 0) {
67
-                LOG(L_ERR, "ERROR: lock_initialize:  retransmission timer semaphore initialization failure\n");
68
-                goto error;
69
-        } */
66
+	for (i=0; i<TG_NR; i++) {
67
+		timer_group_lock[i].semaphore_set = timer_semaphore;
68
+		timer_group_lock[i].semaphore_index = timer_group[ i ];	
69
+	}
70 70
 
71 71
 
72 72
 	i=SEM_MIN;
... ...
@@ -106,10 +114,14 @@ int lock_initialize()
106 106
 			}
107 107
 		}
108 108
 	} while(1);
109
-
110 109
 	sem_nr=i;	
110
+
111
+	reply_semaphore=init_semaphore_set( sem_nr );
112
+	ack_semaphore=init_semaphore_set(sem_nr);
113
+
114
+
111 115
 	/* return success */
112
-	printf("INFO: %d entry semaphores allocated\n", sem_nr );
116
+	LOG(L_INFO, "INFO: semaphore arrays of size %d allocated\n", sem_nr );
113 117
 	return 0;
114 118
 error:
115 119
 	lock_cleanup();
... ...
@@ -117,7 +129,7 @@ error:
117 117
 }
118 118
 
119 119
 /* return -1 if semget failed, -2 if semctl failed */
120
-int init_semaphore_set( int size )
120
+static int init_semaphore_set( int size )
121 121
 {
122 122
 	int new_semaphore, i;
123 123
 
... ...
@@ -160,14 +172,17 @@ void lock_cleanup()
160 160
 	if (entry_semaphore > 0 && 
161 161
 	    semctl( entry_semaphore, 0 , IPC_RMID , 0 )==-1)
162 162
 		LOG(L_ERR, "ERROR: lock_cleanup, entry_semaphore cleanup failed\n");
163
-	if (transaction_timer_semaphore > 0 && 
164
-	    semctl( transaction_timer_semaphore, 0 , IPC_RMID , 0 )==-1)
165
-		LOG(L_ERR, "ERROR: lock_cleanup, transaction_timer_semaphore cleanup failed\n");
166
-	if (retrasmission_timer_semaphore > 0 &&
167
-	    semctl( retrasmission_timer_semaphore, 0 , IPC_RMID , 0 )==-1)
168
-		LOG(L_ERR, "ERROR: lock_cleanup, retrasmission_timer_semaphore cleanup failed\n");
169
-
170
-	entry_semaphore = transaction_timer_semaphore = retrasmission_timer_semaphore = 0;
163
+	if (timer_semaphore > 0 && 
164
+	    semctl( timer_semaphore, 0 , IPC_RMID , 0 )==-1)
165
+		LOG(L_ERR, "ERROR: lock_cleanup, timer_semaphore cleanup failed\n");
166
+	if (reply_semaphore > 0 &&
167
+	    semctl( reply_semaphore, 0 , IPC_RMID , 0 )==-1)
168
+		LOG(L_ERR, "ERROR: lock_cleanup, reply_semaphore cleanup failed\n");
169
+	if (ack_semaphore > 0 &&
170
+	    semctl( ack_semaphore, 0 , IPC_RMID , 0 )==-1)
171
+		LOG(L_ERR, "ERROR: lock_cleanup, ack_semaphore cleanup failed\n");
172
+
173
+	entry_semaphore = timer_semaphore = reply_semaphore = ack_semaphore = 0;
171 174
 
172 175
 }
173 176
 
... ...
@@ -199,8 +214,7 @@ inline int _unlock( ser_lock_t s )
199 199
 	return change_semaphore( s, +1 );
200 200
 }
201 201
 
202
-
203
-int change_semaphore( ser_lock_t s  , int val )
202
+static int change_semaphore( ser_lock_t s  , int val )
204 203
 {
205 204
 	struct sembuf pbuf;
206 205
 	int r;
... ...
@@ -217,27 +231,18 @@ tryagain:
217 217
 			DBG("signal received in a semaphore\n");
218 218
 			goto tryagain;
219 219
 		} else LOG(L_ERR, "ERROR: change_semaphore: %s\n", strerror(errno));
220
-    }
221
-   return r;
220
+	}
221
+	return r;
222 222
 }
223 223
 
224 224
 
225
-/*
226 225
 int init_cell_lock( struct cell *cell )
227 226
 {
228
-*/
229
-	/* just advice which of the available semaphores to use;
230
-		shared with the lock belonging to the next hash entry lock
231
-            (so that there are no collisions if one wants to try to
232
-             lock on a cell as well as its list)
233
-
234
-        */
235
-/*
236
-	cell->mutex.semaphore_set=entry_semaphore,
237
-	cell->mutex.semaphore_index=(cell->hash_index % sem_nr + 1)%sem_nr;
238
-
227
+	cell->reply_mutex.semaphore_set=reply_semaphore;
228
+	cell->reply_mutex.semaphore_index = cell->hash_index % sem_nr;
229
+	cell->ack_mutex.semaphore_set=ack_semaphore;
230
+	cell->ack_mutex.semaphore_index = cell->hash_index % sem_nr;
239 231
 }
240
-*/
241 232
 
242 233
 int init_entry_lock( struct s_table* hash_table, struct entry *entry )
243 234
 {
... ...
@@ -254,28 +259,21 @@ int init_entry_lock( struct s_table* hash_table, struct entry *entry )
254 254
 int init_timerlist_lock( struct s_table* hash_table, enum lists timerlist_id)
255 255
 {
256 256
 	/* each timer list has its own semaphore */
257
-	hash_table->timers[timerlist_id].mutex.semaphore_set=transaction_timer_semaphore;
258
-	hash_table->timers[timerlist_id].mutex.semaphore_index=timerlist_id;
259
-}
260
-/*
261
-int init_retr_timer_lock( struct s_table* hash_table, enum retransmission_lists list_id )
262
-{
263
-	hash_table->retr_timers[list_id].mutex.semaphore_set=retrasmission_timer_semaphore;
264
- 	hash_table->retr_timers[list_id].mutex.semaphore_index=list_id;
257
+	/*
258
+	hash_table->timers[timerlist_id].mutex.semaphore_set=timer_semaphore;
259
+	hash_table->timers[timerlist_id].mutex.semaphore_index=timer_group[timerlist_id];
260
+	*/
261
+
262
+	hash_table->timers[timerlist_id].mutex=timer_group_lock[ timer_group[timerlist_id] ];
265 263
 }
266
-*/
267 264
 
268
-/*
269 265
 int release_cell_lock( struct cell *cell )
270 266
 {
271
-*/
272 267
 	/* don't do anything here -- the init_*_lock procedures
273 268
 	   just advised on usage of shared semaphores but did not
274 269
 	   generate them
275 270
 	*/
276
-/*
277 271
 }
278
-*/
279 272
 
280 273
 int release_entry_lock( struct entry *entry )
281 274
 {
... ...
@@ -286,8 +284,3 @@ release_timerlist_lock( struct timer *timerlist )
286 286
 {
287 287
 	/* the same as above */
288 288
 }
289
-/*
290
-int release_retr_timer_lock( struct timer *timerlist )
291
-{
292
-
293
-} */
... ...
@@ -18,6 +18,16 @@ typedef struct {
18 18
 	int semaphore_index;
19 19
 } ser_lock_t;
20 20
 
21
+enum timer_groups {
22
+	TG_FR,
23
+	TG_WT,
24
+	TG_DEL,
25
+	TG_RT,
26
+	TG_NR
27
+};
28
+
29
+extern ser_lock_t timer_group_lock[TG_NR];
30
+
21 31
 
22 32
 #include "h_table.h"
23 33
 #include "timer.h"
... ...
@@ -27,7 +37,7 @@ typedef struct {
27 27
 
28 28
 
29 29
 int lock_initialize();
30
-int init_semaphore_set( int size );
30
+static int init_semaphore_set( int size );
31 31
 void lock_cleanup();
32 32
 
33 33
 
... ...
@@ -43,12 +53,10 @@ int _unlock( ser_lock_t s );
43 43
 #	define unlock(_s) _unlock( (_s) )
44 44
 #endif
45 45
 
46
-int change_semaphore( ser_lock_t s  , int val );
46
+static int change_semaphore( ser_lock_t s  , int val );
47 47
 
48 48
 int init_cell_lock( struct cell *cell );
49 49
 int init_entry_lock( struct s_table* hash_table, struct entry *entry );
50
-// int init_timerlist_lock( struct s_table* hash_table, enum lists timerlist_id);
51
-//int init_retr_timer_lock( struct s_table* hash_table, enum retransmission_lists list_id );
52 50
 
53 51
 int release_cell_lock( struct cell *cell );
54 52
 int release_entry_lock( struct entry *entry );
... ...
@@ -11,7 +11,6 @@
11 11
 #include "../../ut.h"
12 12
 #include "../../timer.h"
13 13
 
14
-
15 14
 struct cell         *T;
16 15
 unsigned int     global_msg_id;
17 16
 struct s_table*  hash_table;
... ...
@@ -20,10 +19,11 @@ struct s_table*  hash_table;
20 20
 
21 21
 
22 22
 /* determine timer length and put on a correct timer list */
23
-static inline void set_timer( struct s_table *hash_table,
23
+inline void set_timer( struct s_table *hash_table,
24 24
 	struct timer_link *new_tl, enum lists list_id )
25 25
 {
26 26
 	unsigned int timeout;
27
+	struct timer* list;
27 28
 	static enum lists to_table[NR_OF_TIMER_LISTS] =
28 29
 		{	FR_TIME_OUT, INV_FR_TIME_OUT, WT_TIME_OUT, DEL_TIME_OUT,
29 30
 			RETR_T1, RETR_T1 << 1, 	RETR_T1 << 2, RETR_T2 };
... ...
@@ -36,15 +36,25 @@ static inline void set_timer( struct s_table *hash_table,
36 36
 		return;
37 37
 	}
38 38
 	timeout = to_table[ list_id ];
39
+	list= &(hash_table->timers[ list_id ]);
40
+/*
39 41
 	add_to_tail_of_timer_list( &(hash_table->timers[ list_id ]),
40 42
 		new_tl,get_ticks()+timeout);
43
+*/
44
+	lock(  list->mutex );
45
+	/* make sure I'm not already on a list */
46
+	remove_timer_unsafe( new_tl );
47
+	add_timer_unsafe( list, new_tl, get_ticks()+timeout);
48
+	unlock( list->mutex );
41 49
 }
42 50
 
43 51
 /* remove from timer list */
44
-static inline void reset_timer( struct s_table *hash_table,
52
+inline void reset_timer( struct s_table *hash_table,
45 53
 	struct timer_link* tl )
46 54
 {
47
-	remove_from_timer_list( tl );
55
+	lock( timer_group_lock[ tl->tg ] );
56
+	remove_timer_unsafe( tl );
57
+	unlock( timer_group_lock[ tl->tg ] );
48 58
 }
49 59
 
50 60
 static inline void reset_retr_timers( struct s_table *h_table,
... ...
@@ -54,15 +64,29 @@ static inline void reset_retr_timers( struct s_table *h_table,
54 54
 	struct retrans_buff *rb;
55 55
 
56 56
 	DBG("DEBUG:stop_RETR_and_FR_timers : start \n");
57
-	reset_timer( h_table, &(p_cell->outbound_response.retr_timer));
58
-	reset_timer( h_table, &(p_cell->outbound_response.fr_timer));
59
-
57
+	/* lock the first timer list of the FR group -- all other
58
+	   lists share the same lock
59
+	*/
60
+	lock(  hash_table->timers[FR_TIMER_LIST].mutex );
61
+	/* reset_timer( h_table, &(p_cell->outbound_response.retr_timer)); */
62
+	remove_timer_unsafe( & p_cell->outbound_response.retr_timer );
60 63
 	for( ijk=0 ; ijk<(p_cell)->nr_of_outgoings ; ijk++ )  { 
61 64
 			if ( rb = p_cell->outbound_request[ijk] ) {
62
-				reset_timer(h_table, &(rb->retr_timer));
63
-				reset_timer(h_table, &(rb->fr_timer));
65
+				/* reset_timer(h_table, &(rb->retr_timer)); */
66
+				remove_timer_unsafe( & rb->retr_timer );
64 67
 			}
65 68
 		} 
69
+	unlock(  hash_table->timers[FR_TIMER_LIST].mutex );
70
+	lock(  hash_table->timers[RT_T1_TO_1].mutex );
71
+	/* reset_timer( h_table, &(p_cell->outbound_response.fr_timer)); */
72
+	remove_timer_unsafe( & p_cell->outbound_response.fr_timer );
73
+	for( ijk=0 ; ijk<(p_cell)->nr_of_outgoings ; ijk++ )  { 
74
+			if ( rb = p_cell->outbound_request[ijk] ) {
75
+				/* reset_timer(h_table, &(rb->fr_timer)); */
76
+				remove_timer_unsafe( & rb->fr_timer );
77
+			}
78
+		} 
79
+	unlock(  hash_table->timers[RT_T1_TO_1].mutex );
66 80
 	DBG("DEBUG:stop_RETR_and_FR_timers : stop\n");
67 81
 }
68 82
 
... ...
@@ -139,7 +163,7 @@ void tm_shutdown()
139 139
  *       1 - a new transaction was created
140 140
  *      -1 - error, including retransmission
141 141
  */
142
-int t_add_transaction( struct sip_msg* p_msg, char* foo, char* bar )
142
+int t_add_transaction( struct sip_msg* p_msg )
143 143
 {
144 144
    struct cell*    new_cell;
145 145
 
... ...
@@ -153,14 +177,14 @@ int t_add_transaction( struct sip_msg* p_msg, char* foo, char* bar )
153 153
    }
154 154
 
155 155
    /* it's about the same transaction or not?*/
156
-	if (t_check( p_msg , 0 )==-1) return -1;
156
+	/* if (t_check( p_msg , 0 )==-1) return -1; */
157 157
 
158 158
    /* if the lookup's result is not 0 means that it's a retransmission */
159
-   if ( T )
159
+   /* if ( T )
160 160
    {
161 161
       LOG(L_ERR,"ERROR: t_add_transaction: won't add a retransmission\n");
162 162
       return -1;
163
-   }
163
+   } */
164 164
 
165 165
    /* creates a new transaction */
166 166
    new_cell = build_cell( p_msg ) ;
... ...
@@ -181,7 +205,7 @@ int t_add_transaction( struct sip_msg* p_msg, char* foo, char* bar )
181 181
 
182 182
 
183 183
 
184
-
184
+#ifdef _OBSOLETED_TM
185 185
 /* function returns:
186 186
  *       1 - forward successfull
187 187
  *      -1 - error during forward
... ...
@@ -200,14 +224,16 @@ int t_forward( struct sip_msg* p_msg , unsigned int dest_ip_param , unsigned int
200 200
 	branch = 0;	/* we don't do any forking right now */
201 201
 
202 202
 	/* it's about the same transaction or not? */
203
-	if (t_check( p_msg , 0 )==-1) return -1;
203
+	/* if (t_check( p_msg , 0 )==-1) return -1; */
204 204
 
205 205
 	/*if T hasn't been found after all -> return not found (error) */
206
+	/*
206 207
 	if ( !T )
207 208
 	{
208 209
 		DBG("DEBUG: t_forward: no transaction found for request forwarding\n");
209 210
 		return -1;
210 211
 	}
212
+	*/
211 213
 
212 214
 	/*if it's an ACK and the status is not final or is final, but error the
213 215
 	ACK is not forwarded*/
... ...
@@ -281,6 +307,8 @@ int t_forward( struct sip_msg* p_msg , unsigned int dest_ip_param , unsigned int
281 281
 		}
282 282
 		shm_unlock();
283 283
 		memset( rb , 0 , sizeof (struct retrans_buff) );
284
+		rb->retr_timer.tg=TG_RT;
285
+		rb->fr_timer.tg=TG_FR;
284 286
 		rb->retr_buffer = shbuf;
285 287
 		rb->retr_timer.payload =  rb;
286 288
 		rb->fr_timer.payload =  rb;
... ...
@@ -351,7 +379,7 @@ error:
351 351
  *       1 - forward successfull
352 352
  *      -1 - error during forward
353 353
  */
354
-int t_forward_uri( struct sip_msg* p_msg, char* foo, char* bar  )
354
+int t_forward_uri( struct sip_msg* p_msg  )
355 355
 {
356 356
    unsigned int     ip, port;
357 357
 
... ...
@@ -363,186 +391,170 @@ int t_forward_uri( struct sip_msg* p_msg, char* foo, char* bar  )
363 363
 
364 364
    return t_forward( p_msg , ip , port );
365 365
 }
366
+#endif
366 367
 
367 368
 
368
-
369
-
370
-/*  This function is called whenever a reply for our module is received; we need to register
371
-  *  this function on module initialization;
369
+/*  This function is called whenever a reply for our module is received; 
370
+  * we need to register  this function on module initialization;
372 371
   *  Returns :   0 - core router stops
373
-  *                    1 - core router relay statelessly
372
+  *              1 - core router relay statelessly
374 373
   */
375 374
 int t_on_reply_received( struct sip_msg  *p_msg )
376 375
 {
377
-	unsigned int  branch,len, msg_status, msg_class;
378
-	struct sip_msg *clone;
376
+	unsigned int  branch,len, msg_status, msg_class, save_clone;
377
+	struct sip_msg *clone, *backup;
379 378
 	int relay;
379
+	int start_fr;
380
+	int is_invite;
380 381
 	struct retrans_buff *rb;
381 382
 
382
-	clone=NULL;
383 383
 
384
-	/* if a reply received which has not all fields we might want to
385
-	   have for stateul forwarding, give the stateless router
386
-	   a chance for minimum routing; parse only what's needed
387
-	   for MPLS-ize reply matching
388
-	*/
384
+	/* make sure we know the assosociated tranaction ... */
389 385
 	if (t_check( p_msg  , &branch )==-1) return 1;
386
+	/* ... if there is no such, tell the core router to forward statelessly */
387
+	if ( T<=0 ) return 1;
390 388
 
391
-	/* if no T found ->tell the core router to forward statelessly */
392
-	if ( T<=0 )
393
-		return 1;
394 389
 	DBG("DEBUG: t_on_reply_received: Original status =%d\n",T->status);
395 390
 
396
-	/* we were not able to process the response due to memory
397
-	   shortage; simply drop it; hopefuly, we will have more
398
-	memory on the next try */
391
+	/* it can take quite long -- better do it now than later 
392
+	   inside a reply_lock */
393
+	if (!(clone=sip_msg_cloner( p_msg ))) {
394
+		goto error;
395
+	}
399 396
 	msg_status=p_msg->REPLY_STATUS;
400 397
 	msg_class=REPLY_CLASS(p_msg);
401
-	relay = t_should_relay_response( T , msg_status );
402
-
403
-	if (relay && !(clone=sip_msg_cloner( p_msg ))) {
404
-		T_UNREF( T );
405
-		return 0;
406
-	}
398
+	is_invite= T->inbound_request->REQ_METHOD==METHOD_INVITE;
407 399
 
400
+	/* *** stop timers *** */
408 401
 	rb=T->outbound_request[branch];
409
-
410 402
 	/* stop retransmission */
411 403
 	reset_timer( hash_table, &(rb->retr_timer));
412
-
413 404
 	/* stop final response timer only if I got a final response */
414 405
 	if ( msg_class>1 )
415 406
 		reset_timer( hash_table, &(rb->fr_timer));
416
-	/* if a got the first prov. response for an INVITE ->
407
+
408
+	LOCK_REPLIES( T );
409
+   	/* if a got the first prov. response for an INVITE ->
417 410
 	   change FR_TIME_OUT to INV_FR_TIME_UT */
418
-	if (!T->inbound_response[branch] && msg_class==1
419
-	 && T->inbound_request->REQ_METHOD==METHOD_INVITE )
420
-		set_timer( hash_table, &(rb->fr_timer), FR_INV_TIMER_LIST );
421
-	/* get response for INVITE */
422
-	if ( T->inbound_request->REQ_METHOD==METHOD_INVITE )
423
-	{
424
-		if ( T->outbound_request_isACKed[branch] )
425
-		{	/*retransmit the last ACK*/
426
-			DBG("DEBUG: t_on_reply_received: retransmitting ACK!!!!!!!!!!!!!!!!!!+!+!+!!\n");
427
-			SEND_BUFFER( T->outbound_request[branch] );
428
-		} else if (msg_class>2 ) {   /*on a non-200 reply to INVITE*/
429
-			DBG("DEBUG: t_on_reply_received: >=3xx reply to INVITE: send ACK\n");
430
-			if ( t_build_and_send_ACK( T , branch , p_msg )==-1)
431
-			{
432
-				LOG( L_ERR , "ERROR: t_on_reply_received: unable to send ACK\n" );
433
-				if (clone ) sip_msg_free( clone );
434
-				T_UNREF( T );
435
-				return 0;
436
-			}
437
-		}
438
-	}
411
+	start_fr = !T->inbound_response[branch] && msg_class==1 && is_invite;
439 412
 
440
-#	ifdef FORKING
441
-   	/* skipped for the moment*/
442
-#	endif
413
+	/* *** store and relay message as needed *** */
414
+	relay = t_should_relay_response( T , msg_status, branch, &save_clone );
443 415
 
444
-	/* if the incoming response code is not reliable->drop it*/
445
-	if (!relay) {
446
-		T_UNREF( T );
447
-		return 0;
416
+	if (save_clone) {
417
+		/* release previously hold message */
418
+		backup = T->inbound_response[branch];
419
+		T->inbound_response[branch] = clone;
420
+	} else {
421
+		backup = NULL;
422
+		sip_msg_free( clone );
448 423
 	}
449 424
 
450
-	/* restart retransmission if provisional response came for a non_INVITE ->
451
-		retrasmit at RT_T2*/
452
-	if ( msg_class==1 && T->inbound_request->REQ_METHOD!=METHOD_INVITE )
453
-	{
454
-		rb->retr_list = RT_T2;
455
-		set_timer( hash_table, &(rb->retr_timer), RT_T2 );
425
+	if (relay>=0 &&  push_reply_from_uac_to_uas( T, relay)==-1 ) {
426
+		/* restore original state first */
427
+		if (save_clone) T->inbound_response[branch] = backup;
428
+		/* restart FR */
429
+		start_fr=1;
430
+		goto cleanup;
456 431
 	}
457 432
 
458
-	/*store the inbound reply - if there is a previous reply, replace it */
459
-	if ( T->inbound_response[branch] ) {
460
-		sip_msg_free( T->inbound_response[branch] ) ;
461
-		DBG("DEBUG: t_store_incoming_reply: previous inbound reply freed....\n");
462
-	}
463
-	T->inbound_response[branch] = clone;
464 433
 
465
-	if ( msg_class>=3 && msg_class<=5 )
434
+	/* *** ACK handling *** */
435
+	if ( is_invite )
466 436
 	{
467
-		if ( t_all_final(T) && relay_lowest_reply_upstream( T , p_msg )==-1 && clone )
468
-			goto error;
469
-	} else {
470
-		if (push_reply_from_uac_to_uas( T , branch )==-1 && clone )
471
-			goto error;
437
+		if ( T->outbound_ack[branch] )
438
+		{   /*retransmit*/
439
+			SEND_BUFFER( T->outbound_ack[branch] );
440
+		} else if (msg_class>2 ) {   /*on a non-200 reply to INVITE*/
441
+           		DBG("DEBUG: t_on_reply_received: >=3xx reply to INVITE: send ACK\n");
442
+           		if ( t_build_and_send_ACK( T , branch , p_msg )==-1)
443
+           		{
444
+               		LOG( L_ERR , "ERROR: t_on_reply_received: unable to send ACK\n" );
445
+					/* restart FR */
446
+					start_fr=1;
447
+           		}
448
+       		}
449
+   	}
450
+cleanup:
451
+	UNLOCK_REPLIES( T );
452
+	if (backup) sip_msg_free(backup);
453
+	if (start_fr) set_timer( hash_table, &(rb->fr_timer), FR_INV_TIMER_LIST );
454
+   	/* restart retransmission if a provisional response came for 
455
+	   a non_INVITE -> retrasmit at RT_T2*/
456
+	if ( msg_class==1 && !is_invite )
457
+	{
458
+		rb->retr_list = RT_T2;
459
+		set_timer( hash_table, &(rb->retr_timer), RT_T2 );
472 460
 	}
473
-
474
-	/* nothing to do for the ser core */
475
-	T_UNREF( T );
476
-	return 0;
477
-
478 461
 error:
479 462
 	T_UNREF( T );
480
-	T->inbound_response[branch]=NULL;
481
-	sip_msg_free( clone );
482
-	/* don't try to relay statelessly on error */
463
+	/* don't try to relay statelessly on error; on troubles, simply do nothing;
464
+           that will make the other party to retransmit; hopefuly, we'll then 
465
+           be better off */
483 466
 	return 0;
484 467
 }
485 468
 
486
-
487
-int t_on_request_received( struct sip_msg  *p_msg , unsigned int ip , unsigned int port)
469
+#ifdef _OBSOLETED_TM
470
+int t_on_request_received( struct sip_msg  *p_msg , 
471
+	unsigned int ip , unsigned int port)
488 472
 {
489 473
 	if ( t_check( p_msg , 0 ) )
490 474
 	{
491 475
 		if ( p_msg->first_line.u.request.method_value==METHOD_ACK )
492 476
 		{
493
-			LOG( L_INFO , "SER: ACK received -> t_release\n");
477
+			DBG( "SER: ACK received -> t_release\n");
494 478
 			if ( !t_forward( p_msg , ip , port ) )
495 479
 			{
496
-				LOG( L_WARN, "SER: WARNING: bad forward\n");
480
+				DBG( "SER: WARNING: bad forward\n");
497 481
 			}
498 482
 			if ( !t_release_transaction( p_msg ) )
499 483
 			{
500
-				LOG( L_WARN ,"SER: WARNING: bad t_release\n");
484
+				DBG( "SER: WARNING: bad t_release\n");
501 485
 			}
502 486
 		}
503 487
 		else
504 488
 		{
505
-			if ( !t_retransmit_reply( p_msg , 0, 0) )
489
+			if ( !t_retransmit_reply( p_msg ) )
506 490
 			{
507
-				LOG( L_WARN, "SER: WARNING: bad t_retransmit_reply\n");
491
+				DBG( "SER: WARNING: bad t_retransmit_reply\n");
508 492
 			}
509
-			LOG( L_INFO, "SER: yet another annoying retranmission\n");
493
+			DBG( "SER: yet another annoying retranmission\n");
510 494
 		}
511
-		t_unref( p_msg,0,0 );
495
+		t_unref( /* p_msg */ );
512 496
 	} else {
513 497
 		if ( p_msg->first_line.u.request.method_value==METHOD_ACK )
514 498
 		{
515
-			LOG( L_INFO , "SER: forwarding ACK  statelessly\n");
499
+			DBG( "SER: forwarding ACK  statelessly\n");
516 500
 			/* no established transaction ... forward ACK just statelessly*/
517 501
 			forward_request( p_msg , mk_proxy_from_ip(ip,port) );
518 502
 		}
519 503
 		else
520 504
 		{
521 505
 			/* establish transaction*/
522
-			if ( !t_add_transaction(p_msg,0,0) )
506
+			if ( !t_add_transaction(p_msg) )
523 507
 			{
524
-				LOG( L_ERR , "ERROR in ser: t_add_transaction\n");
508
+				DBG( "SER: ERROR in ser: t_add_transaction\n");
525 509
 			}
526 510
 			/* reply */
527 511
 			if ( p_msg->first_line.u.request.method_value==METHOD_CANCEL)
528 512
 			{
529
-				LOG( L_INFO, "SER: new CANCEL\n");
513
+				DBG( "SER: new CANCEL\n");
530 514
 				if ( !t_send_reply( p_msg , 200, "glad to cancel") )
531 515
 				{
532
-					LOG( L_ERR ,"SER:ERROR: t_send_reply\n");
516
+					DBG( "SER:ERROR: t_send_reply\n");
533 517
 				}
534 518
 			} else {
535
-				LOG( L_INFO, "SER: new transaction\n");
519
+				DBG( "SER: new transaction\n");
536 520
 				if ( !t_send_reply( p_msg , 100 , "trying -- your call is important to us") )
537 521
 				{
538
-					LOG( L_ERR, "SER: ERROR: t_send_reply (100)\n");
522
+					DBG( "SER: ERROR: t_send_reply (100)\n");
539 523
 				}
540 524
 			}
541 525
 			if ( !t_forward( p_msg, ip, port ) )
542 526
 			{
543
-				LOG( L_ERR , "SER:ERROR: t_forward \n");
527
+				DBG( "SER:ERROR: t_forward \n");
544 528
 			}
545
-			t_unref( p_msg , 0 , 0);
529
+			t_unref( /* p_msg */ );
546 530
 		}
547 531
 	}
548 532
 
... ...
@@ -565,19 +577,21 @@ int t_on_request_received_uri( struct sip_msg  *p_msg )
565 565
 	return t_on_request_received( p_msg , ip , port );
566 566
 }
567 567
 
568
-
568
+#endif
569 569
 
570 570
 
571 571
 /*   returns 1 if everything was OK or -1 for error
572 572
   */
573 573
 int t_release_transaction( struct sip_msg* p_msg)
574 574
 {
575
+/*
575 576
 	if (t_check( p_msg  , 0 )==-1) return 1;
576 577
 
577 578
    if ( T && T!=T_UNDEFINED )
579
+*/
578 580
       return t_put_on_wait( T );
579 581
 
580
-   return 1;
582
+/*   return 1; */
581 583
 }
582 584
 
583 585
 
... ...
@@ -590,28 +604,32 @@ int t_release_transaction( struct sip_msg* p_msg)
590 590
   * Returns  -1 -error
591 591
   *                1 - OK
592 592
   */
593
-int t_retransmit_reply( struct sip_msg* p_msg, char* foo, char* bar  )
593
+int t_retransmit_reply( struct sip_msg* p_msg   )
594 594
 {
595
-	if (t_check( p_msg  , 0 )==-1) return 1;
595
+/*	if (t_check( p_msg  , 0 )==-1) return 1; */
596 596
 
597 597
    /* if no transaction exists or no reply to be resend -> out */
598
-   if ( T )
598
+/*   if ( T ) */
599 599
    {
600
+	LOCK_REPLIES( T );
600 601
 	SEND_BUFFER( & T->outbound_response );
602
+	UNLOCK_REPLIES( T );
601 603
 	return 1;
602 604
    }
603 605
 
604 606
   /* no transaction found */
605
-   return -1;
607
+/*   return -1; */
606 608
 }
607 609
 
608 610
 
609 611
 
610 612
 
611
-int t_unref( struct sip_msg* p_msg, char* foo, char* bar )
613
+int t_unref( /* struct sip_msg* p_msg */ )
612 614
 {
615
+/*
613 616
 	if (T==T_UNDEFINED || T==T_NULL)
614 617
 		return -1;
618
+*/
615 619
 	T_UNREF( T );
616 620
 	T=T_UNDEFINED;
617 621
 	return 1;
... ...
@@ -626,11 +644,11 @@ int t_unref( struct sip_msg* p_msg, char* foo, char* bar )
626 626
 int t_send_reply(  struct sip_msg* p_msg , unsigned int code , char * text )
627 627
 {
628 628
 	unsigned int len, buf_len;
629
-	char * buf;
629
+	char * buf, *shbuf;
630 630
 	struct retrans_buff *rb;
631 631
 
632 632
 	DBG("DEBUG: t_send_reply: entered\n");
633
-	if (t_check( p_msg , 0 )==-1) return -1;
633
+	/* if (t_check( p_msg , 0 )==-1) return -1;
634 634
 
635 635
 	if (!T)
636 636
 	{
... ...
@@ -638,6 +656,17 @@ int t_send_reply(  struct sip_msg* p_msg , unsigned int code , char * text )
638 638
 			"for which no T-state has been established\n");
639 639
 		return -1;
640 640
 	}
641
+	*/
642
+
643
+	buf = build_res_buf_from_sip_req( code , text , T->inbound_request , &len );
644
+	DBG("DEBUG: t_send_reply: buffer computed\n");
645
+	if (!buf)
646
+	{
647
+		DBG("DEBUG: t_send_reply: response building failed\n");
648
+		goto error;
649
+	}
650
+
651
+	LOCK_REPLIES( T );
641 652
 
642 653
 	rb = & T->outbound_response;
643 654
 	if (!rb->retr_buffer) {
... ...
@@ -650,23 +679,18 @@ int t_send_reply(  struct sip_msg* p_msg , unsigned int code , char * text )
650 650
 			goto error;
651 651
 		}
652 652
 
653
+		rb->retr_timer.tg=TG_RT;
654
+		rb->fr_timer.tg=TG_FR;
653 655
 		rb->retr_timer.payload = rb;
654 656
 		rb->fr_timer.payload = rb;
655 657
 		rb->to.sin_family = AF_INET;
656 658
 		rb->my_T = T;
659
+		rb->reply = code;
657 660
 	}
658 661
 
659
-	buf = build_res_buf_from_sip_req( code , text , T->inbound_request , &len );
660
-	DBG("DEBUG: t_send_reply: buffer computed\n");
661
-	if (!buf)
662
-	{
663
-		DBG("DEBUG: t_send_reply: response building failed\n");
664
-		goto error;
665
-	}
666 662
 
667 663
 	/* if this is a first reply (?100), longer replies will probably follow;
668
-       try avoiding shm_resize by higher buffer size
669
-    */
664
+	   try avoiding shm_resize by higher buffer size */
670 665
 	buf_len = rb->retr_buffer ? len : len + REPLY_OVERBUFFER_LEN;
671 666
 
672 667
 	if (! (rb->retr_buffer = (char*)shm_resize( rb->retr_buffer, buf_len )))
... ...
@@ -676,16 +700,18 @@ int t_send_reply(  struct sip_msg* p_msg , unsigned int code , char * text )
676 676
 	}
677 677
 	rb->bufflen = len ;
678 678
 	memcpy( rb->retr_buffer , buf , len );
679
-	free( buf ) ;
680 679
 	T->status = code;
680
+	SEND_BUFFER( rb );
681
+	/* needs to be protected too because what timers are set depends
682
+	   on current transactions status
683
+	*/
684
+	t_update_timers_after_sending_reply( rb );
685
+	UNLOCK_REPLIES( T );
681 686
 
687
+	free( buf ) ;
682 688
 	/* start/stops the proper timers*/
683
-	DBG("DEBUG: t_send_reply: update timers\n");
684
-	t_update_timers_after_sending_reply( rb );
685 689
 
686
-	DBG("DEBUG: t_send_reply: send reply\n");
687
-	/* t_retransmit_reply( p_msg, 0 , 0); */
688
-	SEND_BUFFER( rb );
690
+	DBG("DEBUG: t_send_reply: finished\n");
689 691
 
690 692
 	return 1;
691 693
 
... ...
@@ -700,7 +726,7 @@ error:
700 700
 /* Push a previously stored reply from UA Client to UA Server
701 701
   * and send it out
702 702
   */
703
-int push_reply_from_uac_to_uas( struct cell* trans , unsigned int branch )
703
+static int push_reply_from_uac_to_uas( struct cell* trans , unsigned int branch )
704 704
 {
705 705
 	char *buf;
706 706
 	unsigned int len, buf_len;
... ...
@@ -719,10 +745,13 @@ int push_reply_from_uac_to_uas( struct cell* trans , unsigned int branch )
719 719
 				trans->inbound_response[branch]->via2->host.s );
720 720
 				goto error;
721 721
 		}
722
+		rb->retr_timer.tg=TG_RT;
723
+		rb->fr_timer.tg=TG_FR;
722 724
 		rb->retr_timer.payload = rb;
723 725
 		rb->fr_timer.payload =  rb;
724 726
 		rb->to.sin_family = AF_INET;
725 727
 		rb->my_T = trans;
728
+		rb->reply = trans->inbound_response[branch]->REPLY_STATUS;
726 729
 
727 730
 	} else {
728 731
 		reset_timer( hash_table, &(rb->retr_timer));
... ...
@@ -752,14 +781,17 @@ int push_reply_from_uac_to_uas( struct cell* trans , unsigned int branch )
752 752
 	/* update the status*/
753 753
 	trans->status = trans->inbound_response[branch]->REPLY_STATUS;
754 754
 	if ( trans->inbound_response[branch]->REPLY_STATUS>=200 &&
755
-	trans->relaied_reply_branch==-1 )
755
+		trans->relaied_reply_branch==-1 ) {
756
+
757
+		memcpy( & trans->ack_to, & trans->outbound_request[ branch ]->to,
758
+			sizeof( struct sockaddr_in ) );
756 759
 		trans->relaied_reply_branch = branch;
760
+	}
757 761
 
758 762
 	/* start/stops the proper timers*/
759 763
 	t_update_timers_after_sending_reply( rb );
760 764
 
761 765
 	/*send the reply*/
762
-	/* t_retransmit_reply( trans->inbound_response[branch], 0 , 0 ); */
763 766
 	SEND_BUFFER( rb );
764 767
 	return 1;
765 768
 
... ...
@@ -778,54 +810,6 @@ error:
778 778
 
779 779
 
780 780
 
781
-/*  Checks if all the transaction's outbound request has a final response.
782
-  *  Return   1 - all are final
783
-  *                0 - some waitting
784
-  */
785
-int t_all_final( struct cell *Trans )
786
-{
787
-   unsigned int i;
788
-
789
-	for( i=0 ; i<Trans->nr_of_outgoings ; i++  )
790
-		if (  !Trans->inbound_response[i] ||
791
-		Trans->inbound_response[i]->REPLY_STATUS<=200 )
792
-			return 0;
793
-
794
-	DBG("DEBUG: t_all_final: final state!!!!:)) \n");
795
-	return 1;
796
-}
797
-
798
-
799
-
800
-
801
-/* Picks the lowest code reply and send it upstream.
802
-  *  Returns -1 if no lowest find reply found (all provisional)
803
-  */
804
-int relay_lowest_reply_upstream( struct cell *Trans , struct sip_msg *p_msg )
805
-{
806
-   unsigned int i            =0 ;
807
-   unsigned int lowest_i = -1;
808
-   int                 lowest_v = 999;
809
-
810
-   for(  ; i<T->nr_of_outgoings ; i++ )
811
-      if ( T->inbound_response[i] &&
812
-	   T->inbound_response[i]->REPLY_STATUS>=200 &&
813
-	   T->inbound_response[i]->REPLY_STATUS<lowest_v )
814
-      {
815
-         lowest_i =i;
816
-         lowest_v = T->inbound_response[i]->REPLY_STATUS;
817
-      }
818
-
819
-   DBG("DEBUG: relay_lowest_reply_upstream: lowest reply [%d]=%d\n",lowest_i,lowest_v);
820
-
821
-   if ( lowest_i != -1 && push_reply_from_uac_to_uas( T ,lowest_i ) == -1 )
822
-	return -1;
823
-
824
-   return lowest_i;
825
-}
826
-
827
-
828
-
829 781
 
830 782
 /*
831 783
   */
... ...
@@ -861,32 +845,79 @@ int t_update_timers_after_sending_reply( struct retrans_buff *rb )
861 861
 /* Checks if the new reply (with new_code status) should be sent or not
862 862
  *  based on the current
863 863
   * transactin status.
864
-  * Returns 1 - the response can be sent
865
-  *         0 - is not indicated to sent
864
+  * Returns 	- branch number (0,1,...) which should be relayed
865
+		- -1 if nothing to be relayed
866 866
   */
867
-int t_should_relay_response( struct cell *Trans , int new_code )
867
+int t_should_relay_response( struct cell *Trans , int new_code, 
868
+	int branch , int *should_store )
868 869
 {
869 870
 	int T_code;
871
+	int b, lowest_b, lowest_s;
870 872
 
871 873
 	T_code = Trans->status;
872 874
 
873
-	if ( T_code >= 200 ) { /* if final response sent out ... */
874
-		if (new_code>=200 && new_code < 300  && /* relay only 2xx */
875
+	/* note: this code never lets replies to CANCEL go through;
876
+	   we generate always a local 200 for CANCEL; 200s are
877
+	   not relayed because it's not an INVITE transaction;
878
+	   >= 300 are not relayed because 200 was already sent
879
+	   out
880
+	*/
881
+
882
+	/* if final response sent out, allow only INVITE 2xx  */
883
+	if ( T_code >= 200 ) { 
884
+		if (new_code>=200 && new_code < 300  && 
875 885
 			Trans->inbound_request->REQ_METHOD==METHOD_INVITE) {
876 886
 			DBG("DBG: t_should_relay: 200 INV after final sent\n");
877
-			return 1;
887
+			*should_store=1;
888
+			return branch;
889
+		} else {
890
+			*should_store=0;
891
+			return -1;
878 892
 		}
879 893
 	} else { /* no final response sent yet */
880
-		if (new_code!=100) { /* all but "100 trying" */
881
-			DBG("DBG: t_should_relay: !=100 -> relay\n");
882
-			return 1;
894
+
895
+		/* negative replies subject to fork picking */
896
+		if (new_code >=300 ) {
897
+			*should_store=1;
898
+			/* if all_final return lowest */
899
+			lowest_b=-1; lowest_s=999;
900
+			for ( b=0; b<Trans->nr_of_outgoings ; b++ ) {
901
+				/* "fake" for the currently processed branch */
902
+				if (b==branch) {
903
+					if (new_code<lowest_s) {
904
+						lowest_b=b;
905
+						lowest_s=new_code;
906
+					}
907
+					continue;
908
+				}
909
+				/* there is still an unfinished UAC transaction; wait now! */
910
+				if ( !Trans->inbound_response[b] ||
911
+					Trans->inbound_response[b]->REPLY_STATUS<200 )
912
+					return -1;
913
+				if ( Trans->inbound_response[b]->REPLY_STATUS<lowest_s )
914
+      				{
915
+         				lowest_b =b;
916
+         				lowest_s = T->inbound_response[b]->REPLY_STATUS;
917
+      				}
918
+			}
919
+			return lowest_b;
920
+
921
+		/* 1xx except 100 and 2xx will be relayed */
922
+		} else if (new_code>100) {
923
+			*should_store=1;
924
+			return branch;
925
+		}
926
+		/* 100 won't be relayed */
927
+		else {
928
+			if (!T->inbound_response[branch]) *should_store=1; 
929
+			else *should_store=0;
930
+			return -1;
883 931
 		}
884 932
 	}
885
-	DBG("DBG: t_should_relay: not to be relayed\n");
886
-	return 0;
887
-}
888
-
889 933
 
934
+	LOG(L_CRIT, "ERROR: Oh my gooosh! We don't know whether to relay\n");
935
+	abort();
936
+}
890 937
 
891 938
 
892 939
 /*
... ...
@@ -895,22 +926,42 @@ int t_put_on_wait(  struct cell  *Trans  )
895 895
 {
896 896
 	struct timer_link *tl;
897 897
 	unsigned int i;
898
+	struct retrans_buff* rb;
899
+
898 900
 	if (is_in_timer_list2( &(Trans->wait_tl)))
899 901
   	{
900 902
 		DBG("DEBUG: t_put_on_wait: already on wait\n");
901 903
 		return 1;
902 904
 	}
903 905
 
906
+	/* remove from  retranssmision  and  final response   list */
904 907
 	DBG("DEBUG: t_put_on_wait: stopping timers (FR and RETR)\n");
905
-	/**/
908
+	reset_retr_timers(hash_table,Trans) ;
909
+
910
+	/* cancel pending client transactions, if any */
906 911
 	for( i=0 ; i<Trans->nr_of_outgoings ; i++ )
907 912
 		if ( Trans->inbound_response[i] && 
908 913
 		REPLY_CLASS(Trans->inbound_response[i])==1)
909 914
 		t_cancel_branch(i);
910 915
 
911
-	/* make double-sure we have finished everything */
912
-	/* remove from  retranssmision  and  final response   list */
913
-	reset_retr_timers(hash_table,Trans) ;
916
+
917
+	/* we don't need outbound requests anymore -- let's save
918
+	   memory and junk them right now!
919
+	*/
920
+/*
921
+	shm_lock();
922
+	for ( i =0 ; i<Trans->nr_of_outgoings;  i++ )
923
+	{
924
+		if ( rb=Trans->outbound_request[i] )
925
+		{
926
+			if (rb->retr_buffer) shm_free_unsafe( rb->retr_buffer );
927
+			Trans->outbound_request[i] = NULL;
928
+			shm_free_unsafe( rb );
929
+		}
930
+	}
931
+	shm_unlock();
932
+*/
933
+
914 934
 	/* adds to Wait list*/
915 935
 	set_timer( hash_table, &(Trans->wait_tl), WT_TIMER_LIST );
916 936
 	return 1;
... ...
@@ -939,6 +990,7 @@ int t_build_and_send_ACK( struct cell *Trans, unsigned int branch, struct sip_ms
939 939
    char *ack_buf, *p, *via;
940 940
    unsigned int len, via_len;
941 941
    int n;
942
+	struct retrans_buff *srb;
942 943
 
943 944
    ack_buf = 0;
944 945
    via =0;
... ...
@@ -948,13 +1000,15 @@ int t_build_and_send_ACK( struct cell *Trans, unsigned int branch, struct sip_ms
948 948
 
949 949
    if ( parse_headers(rpl,HDR_TO)==-1 || !rpl->to )
950 950
    {
951
-	LOG(L_ERR, "ERROR: t_build_and_send_ACK: cannot generate a HBH ACK if key HFs in INVITE missing\n");
951
+	LOG(L_ERR, "ERROR: t_build_and_send_ACK: "
952
+		"cannot generate a HBH ACK if key HFs in reply missing\n");
952 953
 	goto error;
953 954
    }
954 955
 
955 956
     len = 0;
956 957
     /*first line's len */
957
-    len += 4+p_msg->first_line.u.request.uri.len+1+p_msg->first_line.u.request.version.len+CRLF_LEN;
958
+    len += 4+p_msg->first_line.u.request.uri.len+1+
959
+		p_msg->first_line.u.request.version.len+CRLF_LEN;
958 960
     /*via*/
959 961
     via = via_builder( p_msg , &via_len );
960 962
     if (!via)
... ...
@@ -976,12 +1030,13 @@ int t_build_and_send_ACK( struct cell *Trans, unsigned int branch, struct sip_ms
976 976
    /* end of message */
977 977
    len += CRLF_LEN; /*new line*/
978 978
 
979
-   ack_buf = (char *)pkg_malloc( len +1);
980
-   if (!ack_buf)
981
-   {
982
-       LOG(L_ERR, "ERROR: t_build_and_send_ACK: cannot allocate memory\n");
983
-       goto error;
984
-   }
979
+   /* ack_buf = (char *)pkg_malloc( len +1); */
980
+	srb = (struct retrans_buff *) sh_malloc( sizeof(struct retrans_buff) + len + 1 );
981
+	if (!srb) {
982
+		LOG(L_ERR, "ERROR: t_build_and_send_ACK: cannot allocate memory\n");
983
+		goto error1;
984
+	}
985
+	ack_buf = (char *) srb + sizeof(struct retrans_buff);
985 986
 
986 987
    p = ack_buf;
987 988
    DBG("DEBUG: t_build_and_send_ACK: len = %d \n",len);
... ...
@@ -1037,31 +1092,14 @@ int t_build_and_send_ACK( struct cell *Trans, unsigned int branch, struct sip_ms
1037 1037
     memcpy( p , CRLF , CRLF_LEN );
1038 1038
     p += CRLF_LEN;
1039 1039
 
1040
-   /* sends the ACK message to the same destination as the INVITE */
1041
-   udp_send( ack_buf, p-ack_buf, (struct sockaddr*)&(Trans->outbound_request[branch]->to) , sizeof(struct sockaddr_in) );
1042
-
1043
-   /* registering the ACK as received, processed and send */
1044
-   Trans->outbound_request_isACKed[branch] = 1;
1045
-   if ( (Trans->outbound_request[branch]->retr_buffer =
1046
-      (char*)shm_resize( Trans->outbound_request[branch]->retr_buffer, p-ack_buf) ))
1047
-   {
1048
-       memcpy ( Trans->outbound_request[branch]->retr_buffer , ack_buf , p-ack_buf);
1049
-       Trans->outbound_request[branch]->bufflen = p-ack_buf;
1050
-   }
1051
-   else
1052
-       Trans->outbound_request[branch]->bufflen = 0;
1053
-
1054
-
1055
-   DBG("DEBUG: t_build_and_send_ACK: ACK sent\n");
1056
-
1057
-   /* free mem*/
1058
-   if (ack_buf) pkg_free( ack_buf );
1059
-   if (via) pkg_free(via );
1060
-   return 0;
1061
-
1040
+	send_ack( T, branch, srb, p-ack_buf );
1041
+	pkg_free( via );
1042
+	DBG("DEBUG: t_build_and_send_ACK: ACK sent\n");
1043
+	return 0;
1044
+		
1045
+error1:
1046
+   pkg_free(via );
1062 1047
 error:
1063
-   if (ack_buf) free( ack_buf );
1064
-   if (via) pkg_free(via );
1065 1048
    return -1;
1066 1049
 }
1067 1050
 
... ...
@@ -1076,6 +1114,7 @@ void delete_cell( struct cell *p_cell )
1076 1076
 			p_cell);
1077 1077
 		abort();
1078 1078
 	}
1079
+	/*
1079 1080
 	if (is_in_timer_list2(& p_cell->outbound_response.retr_timer )) {
1080 1081
 		LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and still on RETR (rep)\n",
1081 1082
 			p_cell);
... ...
@@ -1098,6 +1137,8 @@ void delete_cell( struct cell *p_cell )
1098 1098
 			abort();
1099 1099
 		}
1100 1100
 	}
1101
+	*/
1102
+	reset_retr_timers( hash_table, p_cell );
1101 1103
 #endif
1102 1104
 	/* still in use ... don't delete */
1103 1105
 	if ( T_IS_REFED(p_cell) ) {
... ...
@@ -1113,7 +1154,7 @@ void delete_cell( struct cell *p_cell )
1113 1113
 		/* it's added to del list for future del */
1114 1114
 		set_timer( hash_table, &(p_cell->dele_tl), DELETE_LIST );
1115 1115
 	} else {
1116
-		DBG("DEBUG: delete_handler : delete transaction %p\n", p_cell );
1116
+		DBG("DEBUG: delete transaction %p\n", p_cell );
1117 1117
 		free_cell( p_cell );
1118 1118
 	}
1119 1119
 }
... ...
@@ -1216,7 +1257,13 @@ void retransmission_handler( void *attr)
1216 1216
 
1217 1217
 	/* retransmision */
1218 1218
 	DBG("DEBUG: retransmission_handler : resending (t=%p)\n", r_buf->my_T);
1219
-	SEND_BUFFER( r_buf );
1219
+	if (r_buf->reply) {
1220
+		LOCK_REPLIES( r_buf->my_T );
1221
+		SEND_BUFFER( r_buf );
1222
+		UNLOCK_REPLIES( r_buf->my_T );
1223
+	} else {
1224
+		SEND_BUFFER( r_buf );
1225
+	}
1220 1226
 
1221 1227
 	id = r_buf->retr_list;
1222 1228
 	r_buf->retr_list = id < RT_T2 ? id + 1 : RT_T2;
... ...
@@ -1286,8 +1333,9 @@ void wait_handler( void *attr)
1286 1286
 	/* the cell is removed from the hash table */
1287 1287
 	DBG("DEBUG: wait_handler : removing %p from table \n", p_cell );
1288 1288
 	remove_from_hash_table( hash_table, p_cell );
1289
+	/* jku: no more here -- we do it when we put a transaction on wait */
1289 1290
 	DBG("DEBUG: wait_handler : stopping all timers\n");
1290
-	reset_retr_timers(hash_table,p_cell) ;
1291
+	reset_retr_timers(hash_table,p_cell) ; 
1291 1292
 	/* put it on DEL_LIST - sch for del */
1292 1293
 #ifdef EXTRA_DEBUG
1293 1294
 	p_cell->damocles = 1;
... ...
@@ -33,6 +33,11 @@ extern struct s_table*  hash_table;
33 33
 #include "sip_msg.h"
34 34
 
35 35
 
36
+#define LOCK_REPLIES(_t) lock((_t)->reply_mutex )
37
+#define UNLOCK_REPLIES(_t) unlock((_t)->reply_mutex )
38
+#define LOCK_ACK(_t) lock((_t)->ack_mutex )
39
+#define UNLOCK_ACK(_t) unlock((_t)->ack_mutex )
40
+
36 41
 
37 42
 /* convenience short-cut macros */
38 43
 #define REQ_METHOD first_line.u.request.method_value
... ...
@@ -112,6 +117,8 @@ extern struct s_table*  hash_table;
112 112
 		DBG_REF("ref", (_T_cell));	})
113 113
 #endif
114 114
 
115
+enum addifnew_status { AIN_ERROR, AIN_RETR, AIN_NEW, AIN_NEWACK, AIN_OLDACK } ;
116
+
115 117
 
116 118
 int   tm_startup();
117 119
 void tm_shutdown();
... ...
@@ -121,7 +128,7 @@ void tm_shutdown();
121 121
  *       1 - a new transaction was created
122 122
  *      -1 - error, including retransmission
123 123
  */
124
-int  t_add_transaction( struct sip_msg* p_msg, char* foo, char* bar  );
124
+int  t_add_transaction( struct sip_msg* p_msg  );
125 125
 
126 126
 
127 127
 
... ...
@@ -149,7 +156,7 @@ int t_forward( struct sip_msg* p_msg , unsigned int dst_ip ,
149 149
  *       1 - forward successfull
150 150
  *      -1 - error during forward
151 151
  */
152
-int t_forward_uri( struct sip_msg* p_msg , char* foo, char* bar );
152
+int t_forward_uri( struct sip_msg* p_msg  );
153 153
 
154 154
 
155 155
 
... ...
@@ -194,7 +201,7 @@ int t_release_transaction( struct sip_msg* );
194 194
   * Returns  -1 -error
195 195
   *                1 - OK
196 196
   */
197
-int t_retransmit_reply( struct sip_msg *, char* , char* );
197
+int t_retransmit_reply( struct sip_msg *  );
198 198
 
199 199
 
200 200