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 18
 	DBG("DEBUG: free_cell: start\n");
20 19
 	/* UA Server */
21 20
 	DBG("DEBUG: free_cell: inbound request %p\n",dead_cell->inbound_request);
21
+	release_cell_lock( dead_cell );
22 22
 	shm_lock();
23 23
 	if ( dead_cell->inbound_request )
24 24
 		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 144
 
142 145
    /* filling with 0 */
143 146
    memset( new_cell, 0, sizeof( struct cell ) );
147
+
148
+	new_cell->outbound_response.retr_timer.tg=TG_RT;
149
+	new_cell->outbound_response.fr_timer.tg=TG_FR;
150
+	new_cell->wait_tl.tg=TG_WT;
151
+	new_cell->dele_tl.tg=TG_DEL;
152
+
144 153
    /* hash index of the entry */
145
-   new_cell->hash_index = hash( p_msg->callid->body , get_cseq(p_msg)->number );
154
+   /* new_cell->hash_index = hash( p_msg->callid->body , get_cseq(p_msg)->number ); */
155
+	new_cell->hash_index = p_msg->hash_index;
146 156
    /* mutex */
147 157
    /* ref counter is 0 */
148 158
    /* all pointers from timers list tl are NULL */
... ...
@@ -153,19 +163,10 @@ struct cell*  build_cell( struct sip_msg* p_msg )
153 163
    DBG("DEBUG: build_cell : clone done\n");
154 164
    if (!new_cell->inbound_request)
155 165
 	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 166
    new_cell->relaied_reply_branch   = -1;
166 167
    new_cell->T_canceled = T_UNDEFINED;
167 168
 
168
-   /* init_cell_lock(  new_cell ); */
169
+    init_cell_lock(  new_cell ); 
169 170
 
170 171
    DBG("DEBUG: build_cell : done\n");
171 172
    return new_cell;
... ...
@@ -181,31 +182,28 @@ error:
181 182
 /*  Takes an already created cell and links it into hash table on the
182 183
   *  appropiate entry.
183 184
   */
184
-void    insert_into_hash_table( struct s_table *hash_table,  struct cell * p_cell )
185
+void    insert_into_hash_table_unsafe( struct s_table *hash_table,  struct cell * p_cell )
185 186
 {
186
-   struct entry* p_entry;
187
-
188
-   /* do we have or not something to insert? */
189
-   if (!p_cell)
190
-      return;
187
+	struct entry* p_entry;
191 188
 
192
-   /* locates the apropiate entry */
193
-   p_entry = &hash_table->entrys[ p_cell->hash_index ];
189
+	/* locates the apropiate entry */
190
+	p_entry = &hash_table->entrys[ p_cell->hash_index ];
194 191
 
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;
192
+	p_cell->label = p_entry->next_label++;
193
+	if ( p_entry->last_cell )
194
+	{
195
+		p_entry->last_cell->next_cell = p_cell;
196
+		p_cell->prev_cell = p_entry->last_cell;
197
+	} else p_entry->first_cell = p_cell;
198
+	
199
+	p_entry->last_cell = p_cell;
200
+}
207 201
 
208
-   unlock( p_entry->mutex );
202
+void insert_into_hash_table( struct s_table *hash_table,  struct cell * p_cell )
203
+{
204
+	lock( hash_table->entrys[ p_cell->hash_index ].mutex );
205
+	insert_into_hash_table_unsafe( hash_table,  p_cell );
206
+	unlock( hash_table->entrys[ p_cell->hash_index ].mutex );
209 207
 }
210 208
 
211 209
 
... ...
@@ -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 78
 
77 79
 	/* useful data */
78 80
 	/* 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;
81
+	struct sip_msg 		*inbound_request;
82
+	struct retrans_buff	outbound_response;
83
+	unsigned int		status;
84
+	str*				tag;
85
+	unsigned int		inbound_request_isACKed;
86
+	int					relaied_reply_branch;
87
+	int					nr_of_outgoings;
86 88
 	/* 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];
89
+	struct retrans_buff	*outbound_request[ MAX_FORK ];
90
+	struct sip_msg		*inbound_response[ MAX_FORK ];
91
+	/* unsigned int		outbound_request_isACKed[MAX_FORK]; */
92
+	struct retrans_buff	*outbound_ack[ MAX_FORK ];
93
+
94
+	/* protection against concurrent reply processing */
95
+	ser_lock_t	reply_mutex;
96
+	/* protection against concurrent ACK processing */
97
+	ser_lock_t	ack_mutex;
98
+
99
+	/* this is where destination is stored for picked branch;
100
+	   good if a need to forward ACK later on
101
+	*/
102
+	struct sockaddr_in ack_to;
90 103
 
91 104
 #ifdef	EXTRA_DEBUG
92 105
 	/* scheduled for deletion ? */
... ...
@@ -125,5 +138,6 @@ void free_cell( struct cell* dead_cell );
125 138
 struct cell*  build_cell( struct sip_msg* p_msg );
126 139
 void remove_from_hash_table( struct s_table *hash_table, struct cell * p_cell );
127 140
 void insert_into_hash_table( struct s_table *hash_table, struct cell * p_cell );
141
+void insert_into_hash_table_unsafe( struct s_table *hash_table, struct cell * p_cell );
128 142
 
129 143
 #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 65
 	DBG("DEBUG: lock_initialize: lock initialization started\n");
58 66
 
59 67
 	/* 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");
68
+	if ((timer_semaphore= init_semaphore_set( TG_NR ) ) < 0) {
69
+                LOG(L_ERR, "ERROR: lock_initialize:  "
70
+			"transaction timer semaphore initialization failure\n");
62 71
 		goto error;
63 72
 	}
64 73
 
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
-        } */
74
+	for (i=0; i<TG_NR; i++) {
75
+		timer_group_lock[i].semaphore_set = timer_semaphore;
76
+		timer_group_lock[i].semaphore_index = timer_group[ i ];	
77
+	}
70 78
 
71 79
 
72 80
 	i=SEM_MIN;
... ...
@@ -106,10 +114,14 @@ int lock_initialize()
106 114
 			}
107 115
 		}
108 116
 	} while(1);
109
-
110 117
 	sem_nr=i;	
118
+
119
+	reply_semaphore=init_semaphore_set( sem_nr );
120
+	ack_semaphore=init_semaphore_set(sem_nr);
121
+
122
+
111 123
 	/* return success */
112
-	printf("INFO: %d entry semaphores allocated\n", sem_nr );
124
+	LOG(L_INFO, "INFO: semaphore arrays of size %d allocated\n", sem_nr );
113 125
 	return 0;
114 126
 error:
115 127
 	lock_cleanup();
... ...
@@ -117,7 +129,7 @@ error:
117 129
 }
118 130
 
119 131
 /* return -1 if semget failed, -2 if semctl failed */
120
-int init_semaphore_set( int size )
132
+static int init_semaphore_set( int size )
121 133
 {
122 134
 	int new_semaphore, i;
123 135
 
... ...
@@ -160,14 +172,17 @@ void lock_cleanup()
160 172
 	if (entry_semaphore > 0 && 
161 173
 	    semctl( entry_semaphore, 0 , IPC_RMID , 0 )==-1)
162 174
 		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;
175
+	if (timer_semaphore > 0 && 
176
+	    semctl( timer_semaphore, 0 , IPC_RMID , 0 )==-1)
177
+		LOG(L_ERR, "ERROR: lock_cleanup, timer_semaphore cleanup failed\n");
178
+	if (reply_semaphore > 0 &&
179
+	    semctl( reply_semaphore, 0 , IPC_RMID , 0 )==-1)
180
+		LOG(L_ERR, "ERROR: lock_cleanup, reply_semaphore cleanup failed\n");
181
+	if (ack_semaphore > 0 &&
182
+	    semctl( ack_semaphore, 0 , IPC_RMID , 0 )==-1)
183
+		LOG(L_ERR, "ERROR: lock_cleanup, ack_semaphore cleanup failed\n");
184
+
185
+	entry_semaphore = timer_semaphore = reply_semaphore = ack_semaphore = 0;
171 186
 
172 187
 }
173 188
 
... ...
@@ -199,8 +214,7 @@ inline int _unlock( ser_lock_t s )
199 214
 	return change_semaphore( s, +1 );
200 215
 }
201 216
 
202
-
203
-int change_semaphore( ser_lock_t s  , int val )
217
+static int change_semaphore( ser_lock_t s  , int val )
204 218
 {
205 219
 	struct sembuf pbuf;
206 220
 	int r;
... ...
@@ -217,27 +231,18 @@ tryagain:
217 231
 			DBG("signal received in a semaphore\n");
218 232
 			goto tryagain;
219 233
 		} else LOG(L_ERR, "ERROR: change_semaphore: %s\n", strerror(errno));
220
-    }
221
-   return r;
234
+	}
235
+	return r;
222 236
 }
223 237
 
224 238
 
225
-/*
226 239
 int init_cell_lock( struct cell *cell )
227 240
 {
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
-
241
+	cell->reply_mutex.semaphore_set=reply_semaphore;
242
+	cell->reply_mutex.semaphore_index = cell->hash_index % sem_nr;
243
+	cell->ack_mutex.semaphore_set=ack_semaphore;
244
+	cell->ack_mutex.semaphore_index = cell->hash_index % sem_nr;
239 245
 }
240
-*/
241 246
 
242 247
 int init_entry_lock( struct s_table* hash_table, struct entry *entry )
243 248
 {
... ...
@@ -254,28 +259,21 @@ int init_entry_lock( struct s_table* hash_table, struct entry *entry )
254 259
 int init_timerlist_lock( struct s_table* hash_table, enum lists timerlist_id)
255 260
 {
256 261
 	/* 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;
262
+	/*
263
+	hash_table->timers[timerlist_id].mutex.semaphore_set=timer_semaphore;
264
+	hash_table->timers[timerlist_id].mutex.semaphore_index=timer_group[timerlist_id];
265
+	*/
266
+
267
+	hash_table->timers[timerlist_id].mutex=timer_group_lock[ timer_group[timerlist_id] ];
265 268
 }
266
-*/
267 269
 
268
-/*
269 270
 int release_cell_lock( struct cell *cell )
270 271
 {
271
-*/
272 272
 	/* don't do anything here -- the init_*_lock procedures
273 273
 	   just advised on usage of shared semaphores but did not
274 274
 	   generate them
275 275
 	*/
276
-/*
277 276
 }
278
-*/
279 277
 
280 278
 int release_entry_lock( struct entry *entry )
281 279
 {
... ...
@@ -286,8 +284,3 @@ release_timerlist_lock( struct timer *timerlist )
286 284
 {
287 285
 	/* the same as above */
288 286
 }
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 37
 
28 38
 
29 39
 int lock_initialize();
30
-int init_semaphore_set( int size );
40
+static int init_semaphore_set( int size );
31 41
 void lock_cleanup();
32 42
 
33 43
 
... ...
@@ -43,12 +53,10 @@ int _unlock( ser_lock_t s );
43 53
 #	define unlock(_s) _unlock( (_s) )
44 54
 #endif
45 55
 
46
-int change_semaphore( ser_lock_t s  , int val );
56
+static int change_semaphore( ser_lock_t s  , int val );
47 57
 
48 58
 int init_cell_lock( struct cell *cell );
49 59
 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 60
 
53 61
 int release_cell_lock( struct cell *cell );
54 62
 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 19
 
21 20
 
22 21
 /* determine timer length and put on a correct timer list */
23
-static inline void set_timer( struct s_table *hash_table,
22
+inline void set_timer( struct s_table *hash_table,
24 23
 	struct timer_link *new_tl, enum lists list_id )
25 24
 {
26 25
 	unsigned int timeout;
26
+	struct timer* list;
27 27
 	static enum lists to_table[NR_OF_TIMER_LISTS] =
28 28
 		{	FR_TIME_OUT, INV_FR_TIME_OUT, WT_TIME_OUT, DEL_TIME_OUT,
29 29
 			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 64
 	struct retrans_buff *rb;
55 65
 
56 66
 	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
-
67
+	/* lock the first timer list of the FR group -- all other
68
+	   lists share the same lock
69
+	*/
70
+	lock(  hash_table->timers[FR_TIMER_LIST].mutex );
71
+	/* reset_timer( h_table, &(p_cell->outbound_response.retr_timer)); */
72
+	remove_timer_unsafe( & p_cell->outbound_response.retr_timer );
60 73
 	for( ijk=0 ; ijk<(p_cell)->nr_of_outgoings ; ijk++ )  { 
61 74
 			if ( rb = p_cell->outbound_request[ijk] ) {
62
-				reset_timer(h_table, &(rb->retr_timer));
63
-				reset_timer(h_table, &(rb->fr_timer));
75
+				/* reset_timer(h_table, &(rb->retr_timer)); */
76
+				remove_timer_unsafe( & rb->retr_timer );
64 77
 			}
65 78
 		} 
79
+	unlock(  hash_table->timers[FR_TIMER_LIST].mutex );
80
+	lock(  hash_table->timers[RT_T1_TO_1].mutex );
81
+	/* reset_timer( h_table, &(p_cell->outbound_response.fr_timer)); */
82
+	remove_timer_unsafe( & p_cell->outbound_response.fr_timer );
83
+	for( ijk=0 ; ijk<(p_cell)->nr_of_outgoings ; ijk++ )  { 
84
+			if ( rb = p_cell->outbound_request[ijk] ) {
85
+				/* reset_timer(h_table, &(rb->fr_timer)); */
86
+				remove_timer_unsafe( & rb->fr_timer );
87
+			}
88
+		} 
89
+	unlock(  hash_table->timers[RT_T1_TO_1].mutex );
66 90
 	DBG("DEBUG:stop_RETR_and_FR_timers : stop\n");
67 91
 }
68 92
 
... ...
@@ -139,7 +163,7 @@ void tm_shutdown()
139 163
  *       1 - a new transaction was created
140 164
  *      -1 - error, including retransmission
141 165
  */
142
-int t_add_transaction( struct sip_msg* p_msg, char* foo, char* bar )
166
+int t_add_transaction( struct sip_msg* p_msg )
143 167
 {
144 168
    struct cell*    new_cell;
145 169
 
... ...
@@ -153,14 +177,14 @@ int t_add_transaction( struct sip_msg* p_msg, char* foo, char* bar )
153 177
    }
154 178
 
155 179
    /* it's about the same transaction or not?*/
156
-	if (t_check( p_msg , 0 )==-1) return -1;
180
+	/* if (t_check( p_msg , 0 )==-1) return -1; */
157 181
 
158 182
    /* if the lookup's result is not 0 means that it's a retransmission */
159
-   if ( T )
183
+   /* if ( T )
160 184
    {
161 185
       LOG(L_ERR,"ERROR: t_add_transaction: won't add a retransmission\n");
162 186
       return -1;
163
-   }
187
+   } */
164 188
 
165 189
    /* creates a new transaction */
166 190
    new_cell = build_cell( p_msg ) ;
... ...
@@ -181,7 +205,7 @@ int t_add_transaction( struct sip_msg* p_msg, char* foo, char* bar )
181 205
 
182 206
 
183 207
 
184
-
208
+#ifdef _OBSOLETED_TM
185 209
 /* function returns:
186 210
  *       1 - forward successfull
187 211
  *      -1 - error during forward
... ...
@@ -200,14 +224,16 @@ int t_forward( struct sip_msg* p_msg , unsigned int dest_ip_param , unsigned int
200 224
 	branch = 0;	/* we don't do any forking right now */
201 225
 
202 226
 	/* it's about the same transaction or not? */
203
-	if (t_check( p_msg , 0 )==-1) return -1;
227
+	/* if (t_check( p_msg , 0 )==-1) return -1; */
204 228
 
205 229
 	/*if T hasn't been found after all -> return not found (error) */
230
+	/*
206 231
 	if ( !T )
207 232
 	{
208 233
 		DBG("DEBUG: t_forward: no transaction found for request forwarding\n");
209 234
 		return -1;
210 235
 	}
236
+	*/
211 237
 
212 238
 	/*if it's an ACK and the status is not final or is final, but error the
213 239
 	ACK is not forwarded*/
... ...
@@ -281,6 +307,8 @@ int t_forward( struct sip_msg* p_msg , unsigned int dest_ip_param , unsigned int
281 307
 		}
282 308
 		shm_unlock();
283 309
 		memset( rb , 0 , sizeof (struct retrans_buff) );
310
+		rb->retr_timer.tg=TG_RT;
311
+		rb->fr_timer.tg=TG_FR;
284 312
 		rb->retr_buffer = shbuf;
285 313
 		rb->retr_timer.payload =  rb;
286 314
 		rb->fr_timer.payload =  rb;
... ...
@@ -351,7 +379,7 @@ error:
351 379
  *       1 - forward successfull
352 380
  *      -1 - error during forward
353 381
  */
354
-int t_forward_uri( struct sip_msg* p_msg, char* foo, char* bar  )
382
+int t_forward_uri( struct sip_msg* p_msg  )
355 383
 {
356 384
    unsigned int     ip, port;
357 385
 
... ...
@@ -363,186 +391,170 @@ int t_forward_uri( struct sip_msg* p_msg, char* foo, char* bar  )
363 391
 
364 392
    return t_forward( p_msg , ip , port );
365 393
 }
394
+#endif
366 395
 
367 396
 
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;
397
+/*  This function is called whenever a reply for our module is received; 
398
+  * we need to register  this function on module initialization;
372 399
   *  Returns :   0 - core router stops
373
-  *                    1 - core router relay statelessly
400
+  *              1 - core router relay statelessly
374 401
   */
375 402
 int t_on_reply_received( struct sip_msg  *p_msg )
376 403
 {
377
-	unsigned int  branch,len, msg_status, msg_class;
378
-	struct sip_msg *clone;
404
+	unsigned int  branch,len, msg_status, msg_class, save_clone;
405
+	struct sip_msg *clone, *backup;
379 406
 	int relay;
407
+	int start_fr;
408
+	int is_invite;
380 409
 	struct retrans_buff *rb;
381 410
 
382
-	clone=NULL;
383 411
 
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
-	*/
412
+	/* make sure we know the assosociated tranaction ... */
389 413
 	if (t_check( p_msg  , &branch )==-1) return 1;
414
+	/* ... if there is no such, tell the core router to forward statelessly */
415
+	if ( T<=0 ) return 1;
390 416
 
391
-	/* if no T found ->tell the core router to forward statelessly */
392
-	if ( T<=0 )
393
-		return 1;
394 417
 	DBG("DEBUG: t_on_reply_received: Original status =%d\n",T->status);
395 418
 
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 */
419
+	/* it can take quite long -- better do it now than later 
420
+	   inside a reply_lock */
421
+	if (!(clone=sip_msg_cloner( p_msg ))) {
422
+		goto error;
423
+	}
399 424
 	msg_status=p_msg->REPLY_STATUS;
400 425
 	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
-	}
426
+	is_invite= T->inbound_request->REQ_METHOD==METHOD_INVITE;
407 427
 
428
+	/* *** stop timers *** */
408 429
 	rb=T->outbound_request[branch];
409
-
410 430
 	/* stop retransmission */
411 431
 	reset_timer( hash_table, &(rb->retr_timer));
412
-
413 432
 	/* stop final response timer only if I got a final response */
414 433
 	if ( msg_class>1 )
415 434
 		reset_timer( hash_table, &(rb->fr_timer));
416
-	/* if a got the first prov. response for an INVITE ->
435
+
436
+	LOCK_REPLIES( T );
437
+   	/* if a got the first prov. response for an INVITE ->
417 438
 	   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
-	}
439
+	start_fr = !T->inbound_response[branch] && msg_class==1 && is_invite;
439 440
 
440
-#	ifdef FORKING
441
-   	/* skipped for the moment*/
442
-#	endif
441
+	/* *** store and relay message as needed *** */
442
+	relay = t_should_relay_response( T , msg_status, branch, &save_clone );
443 443
 
444
-	/* if the incoming response code is not reliable->drop it*/
445
-	if (!relay) {
446
-		T_UNREF( T );
447
-		return 0;
444
+	if (save_clone) {
445
+		/* release previously hold message */
446
+		backup = T->inbound_response[branch];
447
+		T->inbound_response[branch] = clone;
448
+	} else {
449
+		backup = NULL;
450
+		sip_msg_free( clone );
448 451
 	}
449 452
 
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 );
453
+	if (relay>=0 &&  push_reply_from_uac_to_uas( T, relay)==-1 ) {
454
+		/* restore original state first */
455
+		if (save_clone) T->inbound_response[branch] = backup;
456
+		/* restart FR */
457
+		start_fr=1;
458
+		goto cleanup;
456 459
 	}
457 460
 
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 461
 
465
-	if ( msg_class>=3 && msg_class<=5 )
462
+	/* *** ACK handling *** */
463
+	if ( is_invite )
466 464
 	{
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;
465
+		if ( T->outbound_ack[branch] )
466
+		{   /*retransmit*/
467
+			SEND_BUFFER( T->outbound_ack[branch] );
468
+		} else if (msg_class>2 ) {   /*on a non-200 reply to INVITE*/
469
+           		DBG("DEBUG: t_on_reply_received: >=3xx reply to INVITE: send ACK\n");
470
+           		if ( t_build_and_send_ACK( T , branch , p_msg )==-1)
471
+           		{
472
+               		LOG( L_ERR , "ERROR: t_on_reply_received: unable to send ACK\n" );
473
+					/* restart FR */
474
+					start_fr=1;
475
+           		}
476
+       		}
477
+   	}
478
+cleanup:
479
+	UNLOCK_REPLIES( T );
480
+	if (backup) sip_msg_free(backup);
481
+	if (start_fr) set_timer( hash_table, &(rb->fr_timer), FR_INV_TIMER_LIST );
482
+   	/* restart retransmission if a provisional response came for 
483
+	   a non_INVITE -> retrasmit at RT_T2*/
484
+	if ( msg_class==1 && !is_invite )
485
+	{
486
+		rb->retr_list = RT_T2;
487
+		set_timer( hash_table, &(rb->retr_timer), RT_T2 );
472 488
 	}
473
-
474
-	/* nothing to do for the ser core */
475
-	T_UNREF( T );
476
-	return 0;
477
-
478 489
 error:
479 490
 	T_UNREF( T );
480
-	T->inbound_response[branch]=NULL;
481
-	sip_msg_free( clone );
482
-	/* don't try to relay statelessly on error */
491
+	/* don't try to relay statelessly on error; on troubles, simply do nothing;
492
+           that will make the other party to retransmit; hopefuly, we'll then 
493
+           be better off */
483 494
 	return 0;
484 495
 }
485 496
 
486
-
487
-int t_on_request_received( struct sip_msg  *p_msg , unsigned int ip , unsigned int port)
497
+#ifdef _OBSOLETED_TM
498
+int t_on_request_received( struct sip_msg  *p_msg , 
499
+	unsigned int ip , unsigned int port)
488 500
 {
489 501
 	if ( t_check( p_msg , 0 ) )
490 502
 	{
491 503
 		if ( p_msg->first_line.u.request.method_value==METHOD_ACK )
492 504
 		{
493
-			LOG( L_INFO , "SER: ACK received -> t_release\n");
505
+			DBG( "SER: ACK received -> t_release\n");
494 506
 			if ( !t_forward( p_msg , ip , port ) )
495 507
 			{
496
-				LOG( L_WARN, "SER: WARNING: bad forward\n");
508
+				DBG( "SER: WARNING: bad forward\n");
497 509
 			}
498 510
 			if ( !t_release_transaction( p_msg ) )
499 511
 			{
500
-				LOG( L_WARN ,"SER: WARNING: bad t_release\n");
512
+				DBG( "SER: WARNING: bad t_release\n");
501 513
 			}
502 514
 		}
503 515
 		else
504 516
 		{
505
-			if ( !t_retransmit_reply( p_msg , 0, 0) )
517
+			if ( !t_retransmit_reply( p_msg ) )
506 518
 			{
507
-				LOG( L_WARN, "SER: WARNING: bad t_retransmit_reply\n");
519
+				DBG( "SER: WARNING: bad t_retransmit_reply\n");
508 520
 			}
509
-			LOG( L_INFO, "SER: yet another annoying retranmission\n");
521
+			DBG( "SER: yet another annoying retranmission\n");
510 522
 		}
511
-		t_unref( p_msg,0,0 );
523
+		t_unref( /* p_msg */ );
512 524
 	} else {
513 525
 		if ( p_msg->first_line.u.request.method_value==METHOD_ACK )
514 526
 		{
515
-			LOG( L_INFO , "SER: forwarding ACK  statelessly\n");
527
+			DBG( "SER: forwarding ACK  statelessly\n");
516 528
 			/* no established transaction ... forward ACK just statelessly*/
517 529
 			forward_request( p_msg , mk_proxy_from_ip(ip,port) );
518 530
 		}
519 531
 		else
520 532
 		{
521 533
 			/* establish transaction*/
522
-			if ( !t_add_transaction(p_msg,0,0) )
534
+			if ( !t_add_transaction(p_msg) )
523 535
 			{
524
-				LOG( L_ERR , "ERROR in ser: t_add_transaction\n");
536
+				DBG( "SER: ERROR in ser: t_add_transaction\n");
525 537
 			}
526 538
 			/* reply */
527 539
 			if ( p_msg->first_line.u.request.method_value==METHOD_CANCEL)
528 540
 			{
529
-				LOG( L_INFO, "SER: new CANCEL\n");
541
+				DBG( "SER: new CANCEL\n");
530 542
 				if ( !t_send_reply( p_msg , 200, "glad to cancel") )
531 543
 				{
532
-					LOG( L_ERR ,"SER:ERROR: t_send_reply\n");
544
+					DBG( "SER:ERROR: t_send_reply\n");
533 545
 				}
534 546
 			} else {
535
-				LOG( L_INFO, "SER: new transaction\n");
547
+				DBG( "SER: new transaction\n");
536 548
 				if ( !t_send_reply( p_msg , 100 , "trying -- your call is important to us") )
537 549
 				{
538
-					LOG( L_ERR, "SER: ERROR: t_send_reply (100)\n");
550
+					DBG( "SER: ERROR: t_send_reply (100)\n");
539 551
 				}
540 552
 			}
541 553
 			if ( !t_forward( p_msg, ip, port ) )
542 554
 			{
543
-				LOG( L_ERR , "SER:ERROR: t_forward \n");
555
+				DBG( "SER:ERROR: t_forward \n");
544 556
 			}
545
-			t_unref( p_msg , 0 , 0);
557
+			t_unref( /* p_msg */ );
546 558
 		}
547 559
 	}
548 560
 
... ...
@@ -565,19 +577,21 @@ int t_on_request_received_uri( struct sip_msg  *p_msg )
565 577
 	return t_on_request_received( p_msg , ip , port );
566 578
 }
567 579
 
568
-
580
+#endif
569 581
 
570 582
 
571 583
 /*   returns 1 if everything was OK or -1 for error
572 584
   */
573 585
 int t_release_transaction( struct sip_msg* p_msg)
574 586
 {
587
+/*
575 588
 	if (t_check( p_msg  , 0 )==-1) return 1;
576 589
 
577 590
    if ( T && T!=T_UNDEFINED )
591
+*/
578 592
       return t_put_on_wait( T );
579 593
 
580
-   return 1;
594
+/*   return 1; */
581 595
 }
582 596
 
583 597
 
... ...
@@ -590,28 +604,32 @@ int t_release_transaction( struct sip_msg* p_msg)
590 604
   * Returns  -1 -error
591 605
   *                1 - OK
592 606
   */
593
-int t_retransmit_reply( struct sip_msg* p_msg, char* foo, char* bar  )
607
+int t_retransmit_reply( struct sip_msg* p_msg   )
594 608
 {
595
-	if (t_check( p_msg  , 0 )==-1) return 1;
609
+/*	if (t_check( p_msg  , 0 )==-1) return 1; */
596 610
 
597 611
    /* if no transaction exists or no reply to be resend -> out */
598
-   if ( T )
612
+/*   if ( T ) */
599 613
    {
614
+	LOCK_REPLIES( T );
600 615
 	SEND_BUFFER( & T->outbound_response );
616
+	UNLOCK_REPLIES( T );
601 617
 	return 1;
602 618
    }
603 619
 
604 620
   /* no transaction found */
605
-   return -1;
621
+/*   return -1; */
606 622
 }
607 623
 
608 624
 
609 625
 
610 626
 
611
-int t_unref( struct sip_msg* p_msg, char* foo, char* bar )
627
+int t_unref( /* struct sip_msg* p_msg */ )
612 628
 {
629
+/*
613 630
 	if (T==T_UNDEFINED || T==T_NULL)
614 631
 		return -1;
632
+*/
615 633
 	T_UNREF( T );
616 634
 	T=T_UNDEFINED;
617 635
 	return 1;
... ...
@@ -626,11 +644,11 @@ int t_unref( struct sip_msg* p_msg, char* foo, char* bar )
626 644
 int t_send_reply(  struct sip_msg* p_msg , unsigned int code , char * text )
627 645
 {
628 646
 	unsigned int len, buf_len;
629
-	char * buf;
647
+	char * buf, *shbuf;
630 648
 	struct retrans_buff *rb;
631 649
 
632 650
 	DBG("DEBUG: t_send_reply: entered\n");
633
-	if (t_check( p_msg , 0 )==-1) return -1;
651
+	/* if (t_check( p_msg , 0 )==-1) return -1;
634 652
 
635 653
 	if (!T)
636 654
 	{
... ...
@@ -638,6 +656,17 @@ int t_send_reply(  struct sip_msg* p_msg , unsigned int code , char * text )
638 656
 			"for which no T-state has been established\n");
639 657
 		return -1;
640 658
 	}
659
+	*/
660
+
661
+	buf = build_res_buf_from_sip_req( code , text , T->inbound_request , &len );
662
+	DBG("DEBUG: t_send_reply: buffer computed\n");
663
+	if (!buf)
664
+	{
665
+		DBG("DEBUG: t_send_reply: response building failed\n");
666
+		goto error;
667
+	}
668
+
669
+	LOCK_REPLIES( T );
641 670
 
642 671
 	rb = & T->outbound_response;
643 672
 	if (!rb->retr_buffer) {
... ...
@@ -650,23 +679,18 @@ int t_send_reply(  struct sip_msg* p_msg , unsigned int code , char * text )
650 679
 			goto error;
651 680
 		}
652 681
 
682
+		rb->retr_timer.tg=TG_RT;
683
+		rb->fr_timer.tg=TG_FR;
653 684
 		rb->retr_timer.payload = rb;
654 685
 		rb->fr_timer.payload = rb;
655 686
 		rb->to.sin_family = AF_INET;
656 687
 		rb->my_T = T;
688
+		rb->reply = code;
657 689
 	}
658 690
 
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 691
 
667 692
 	/* if this is a first reply (?100), longer replies will probably follow;
668
-       try avoiding shm_resize by higher buffer size
669
-    */
693
+	   try avoiding shm_resize by higher buffer size */
670 694
 	buf_len = rb->retr_buffer ? len : len + REPLY_OVERBUFFER_LEN;
671 695
 
672 696
 	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 700
 	}
677 701
 	rb->bufflen = len ;
678 702
 	memcpy( rb->retr_buffer , buf , len );
679
-	free( buf ) ;
680 703
 	T->status = code;
704
+	SEND_BUFFER( rb );
705
+	/* needs to be protected too because what timers are set depends
706
+	   on current transactions status
707
+	*/
708
+	t_update_timers_after_sending_reply( rb );
709
+	UNLOCK_REPLIES( T );
681 710
 
711
+	free( buf ) ;
682 712
 	/* start/stops the proper timers*/
683
-	DBG("DEBUG: t_send_reply: update timers\n");
684
-	t_update_timers_after_sending_reply( rb );
685 713
 
686
-	DBG("DEBUG: t_send_reply: send reply\n");
687
-	/* t_retransmit_reply( p_msg, 0 , 0); */
688
-	SEND_BUFFER( rb );
714
+	DBG("DEBUG: t_send_reply: finished\n");
689 715
 
690 716
 	return 1;
691 717
 
... ...
@@ -700,7 +726,7 @@ error:
700 726
 /* Push a previously stored reply from UA Client to UA Server
701 727
   * and send it out
702 728
   */
703
-int push_reply_from_uac_to_uas( struct cell* trans , unsigned int branch )
729
+static int push_reply_from_uac_to_uas( struct cell* trans , unsigned int branch )
704 730
 {
705 731
 	char *buf;
706 732
 	unsigned int len, buf_len;
... ...
@@ -719,10 +745,13 @@ int push_reply_from_uac_to_uas( struct cell* trans , unsigned int branch )
719 745
 				trans->inbound_response[branch]->via2->host.s );
720 746
 				goto error;
721 747
 		}
748
+		rb->retr_timer.tg=TG_RT;
749
+		rb->fr_timer.tg=TG_FR;
722 750
 		rb->retr_timer.payload = rb;
723 751
 		rb->fr_timer.payload =  rb;
724 752
 		rb->to.sin_family = AF_INET;
725 753
 		rb->my_T = trans;
754
+		rb->reply = trans->inbound_response[branch]->REPLY_STATUS;
726 755
 
727 756
 	} else {
728 757
 		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 781
 	/* update the status*/
753 782
 	trans->status = trans->inbound_response[branch]->REPLY_STATUS;
754 783
 	if ( trans->inbound_response[branch]->REPLY_STATUS>=200 &&
755
-	trans->relaied_reply_branch==-1 )
784
+		trans->relaied_reply_branch==-1 ) {
785
+
786
+		memcpy( & trans->ack_to, & trans->outbound_request[ branch ]->to,
787
+			sizeof( struct sockaddr_in ) );
756 788
 		trans->relaied_reply_branch = branch;
789
+	}
757 790
 
758 791
 	/* start/stops the proper timers*/
759 792
 	t_update_timers_after_sending_reply( rb );
760 793
 
761 794
 	/*send the reply*/
762
-	/* t_retransmit_reply( trans->inbound_response[branch], 0 , 0 ); */
763 795
 	SEND_BUFFER( rb );
764 796
 	return 1;
765 797
 
... ...
@@ -778,54 +810,6 @@ error:
778 810
 
779 811
 
780 812
 
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 813
 
830 814
 /*
831 815
   */
... ...
@@ -861,32 +845,79 @@ int t_update_timers_after_sending_reply( struct retrans_buff *rb )
861 845
 /* Checks if the new reply (with new_code status) should be sent or not
862 846
  *  based on the current
863 847
   * transactin status.
864
-  * Returns 1 - the response can be sent
865
-  *         0 - is not indicated to sent
848
+  * Returns 	- branch number (0,1,...) which should be relayed
849
+		- -1 if nothing to be relayed
866 850
   */
867
-int t_should_relay_response( struct cell *Trans , int new_code )
851
+int t_should_relay_response( struct cell *Trans , int new_code, 
852
+	int branch , int *should_store )
868 853
 {
869 854
 	int T_code;
855
+	int b, lowest_b, lowest_s;
870 856
 
871 857
 	T_code = Trans->status;
872 858
 
873
-	if ( T_code >= 200 ) { /* if final response sent out ... */
874
-		if (new_code>=200 && new_code < 300  && /* relay only 2xx */
859
+	/* note: this code never lets replies to CANCEL go through;
860
+	   we generate always a local 200 for CANCEL; 200s are
861
+	   not relayed because it's not an INVITE transaction;
862
+	   >= 300 are not relayed because 200 was already sent
863
+	   out
864
+	*/
865
+
866
+	/* if final response sent out, allow only INVITE 2xx  */
867
+	if ( T_code >= 200 ) { 
868
+		if (new_code>=200 && new_code < 300  && 
875 869
 			Trans->inbound_request->REQ_METHOD==METHOD_INVITE) {
876 870
 			DBG("DBG: t_should_relay: 200 INV after final sent\n");
877
-			return 1;
871
+			*should_store=1;
872
+			return branch;
873
+		} else {
874
+			*should_store=0;
875
+			return -1;
878 876
 		}
879 877
 	} 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;
878
+
879
+		/* negative replies subject to fork picking */
880
+		if (new_code >=300 ) {
881
+			*should_store=1;
882
+			/* if all_final return lowest */
883
+			lowest_b=-1; lowest_s=999;
884
+			for ( b=0; b<Trans->nr_of_outgoings ; b++ ) {
885
+				/* "fake" for the currently processed branch */
886
+				if (b==branch) {
887
+					if (new_code<lowest_s) {
888
+						lowest_b=b;
889
+						lowest_s=new_code;
890
+					}
891
+					continue;
892
+				}
893
+				/* there is still an unfinished UAC transaction; wait now! */
894
+				if ( !Trans->inbound_response[b] ||
895
+					Trans->inbound_response[b]->REPLY_STATUS<200 )
896
+					return -1;
897
+				if ( Trans->inbound_response[b]->REPLY_STATUS<lowest_s )
898
+      				{
899
+         				lowest_b =b;
900
+         				lowest_s = T->inbound_response[b]->REPLY_STATUS;
901
+      				}
902
+			}
903
+			return lowest_b;
904
+
905
+		/* 1xx except 100 and 2xx will be relayed */
906
+		} else if (new_code>100) {
907
+			*should_store=1;
908
+			return branch;
909
+		}
910
+		/* 100 won't be relayed */
911
+		else {
912
+			if (!T->inbound_response[branch]) *should_store=1; 
913
+			else *should_store=0;
914
+			return -1;
883 915
 		}
884 916
 	}
885
-	DBG("DBG: t_should_relay: not to be relayed\n");
886
-	return 0;
887
-}
888
-
889 917
 
918
+	LOG(L_CRIT, "ERROR: Oh my gooosh! We don't know whether to relay\n");
919
+	abort();
920
+}
890 921
 
891 922
 
892 923
 /*
... ...
@@ -895,22 +926,42 @@ int t_put_on_wait(  struct cell  *Trans  )
895 926
 {
896 927
 	struct timer_link *tl;
897 928
 	unsigned int i;
929
+	struct retrans_buff* rb;
930
+
898 931
 	if (is_in_timer_list2( &(Trans->wait_tl)))
899 932
   	{
900 933
 		DBG("DEBUG: t_put_on_wait: already on wait\n");
901 934
 		return 1;
902 935
 	}
903 936
 
937
+	/* remove from  retranssmision  and  final response   list */
904 938
 	DBG("DEBUG: t_put_on_wait: stopping timers (FR and RETR)\n");
905
-	/**/
939
+	reset_retr_timers(hash_table,Trans) ;
940
+
941
+	/* cancel pending client transactions, if any */
906 942
 	for( i=0 ; i<Trans->nr_of_outgoings ; i++ )
907 943
 		if ( Trans->inbound_response[i] && 
908 944
 		REPLY_CLASS(Trans->inbound_response[i])==1)
909 945
 		t_cancel_branch(i);
910 946
 
911
-	/* make double-sure we have finished everything */
912
-	/* remove from  retranssmision  and  final response   list */
913
-	reset_retr_timers(hash_table,Trans) ;
947
+
948
+	/* we don't need outbound requests anymore -- let's save
949
+	   memory and junk them right now!
950
+	*/
951
+/*
952
+	shm_lock();
953
+	for ( i =0 ; i<Trans->nr_of_outgoings;  i++ )
954
+	{
955
+		if ( rb=Trans->outbound_request[i] )
956
+		{
957
+			if (rb->retr_buffer) shm_free_unsafe( rb->retr_buffer );
958
+			Trans->outbound_request[i] = NULL;
959
+			shm_free_unsafe( rb );
960
+		}
961
+	}
962
+	shm_unlock();
963
+*/
964
+
914 965
 	/* adds to Wait list*/
915 966
 	set_timer( hash_table, &(Trans->wait_tl), WT_TIMER_LIST );
916 967
 	return 1;
... ...
@@ -939,6 +990,7 @@ int t_build_and_send_ACK( struct cell *Trans, unsigned int branch, struct sip_ms
939 990
    char *ack_buf, *p, *via;
940 991
    unsigned int len, via_len;
941 992
    int n;
993
+	struct retrans_buff *srb;
942 994
 
943 995
    ack_buf = 0;
944 996
    via =0;
... ...
@@ -948,13 +1000,15 @@ int t_build_and_send_ACK( struct cell *Trans, unsigned int branch, struct sip_ms
948 1000
 
949 1001
    if ( parse_headers(rpl,HDR_TO)==-1 || !rpl->to )
950 1002
    {
951
-	LOG(L_ERR, "ERROR: t_build_and_send_ACK: cannot generate a HBH ACK if key HFs in INVITE missing\n");
1003
+	LOG(L_ERR, "ERROR: t_build_and_send_ACK: "
1004
+		"cannot generate a HBH ACK if key HFs in reply missing\n");
952 1005
 	goto error;
953 1006
    }
954 1007
 
955 1008
     len = 0;
956 1009
     /*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;
1010
+    len += 4+p_msg->first_line.u.request.uri.len+1+
1011
+		p_msg->first_line.u.request.version.len+CRLF_LEN;
958 1012
     /*via*/
959 1013
     via = via_builder( p_msg , &via_len );
960 1014
     if (!via)
... ...
@@ -976,12 +1030,13 @@ int t_build_and_send_ACK( struct cell *Trans, unsigned int branch, struct sip_ms
976 1030
    /* end of message */
977 1031
    len += CRLF_LEN; /*new line*/
978 1032
 
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
-   }
1033
+   /* ack_buf = (char *)pkg_malloc( len +1); */
1034
+	srb = (struct retrans_buff *) sh_malloc( sizeof(struct retrans_buff) + len + 1 );
1035
+	if (!srb) {
1036
+		LOG(L_ERR, "ERROR: t_build_and_send_ACK: cannot allocate memory\n");
1037
+		goto error1;
1038
+	}
1039
+	ack_buf = (char *) srb + sizeof(struct retrans_buff);
985 1040
 
986 1041
    p = ack_buf;
987 1042
    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 1092
     memcpy( p , CRLF , CRLF_LEN );
1038 1093
     p += CRLF_LEN;
1039 1094
 
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
-
1095
+	send_ack( T, branch, srb, p-ack_buf );
1096
+	pkg_free( via );
1097
+	DBG("DEBUG: t_build_and_send_ACK: ACK sent\n");
1098
+	return 0;
1099
+		
1100
+error1:
1101
+   pkg_free(via );
1062 1102
 error:
1063
-   if (ack_buf) free( ack_buf );
1064
-   if (via) pkg_free(via );
1065 1103
    return -1;
1066 1104
 }
1067 1105
 
... ...
@@ -1076,6 +1114,7 @@ void delete_cell( struct cell *p_cell )
1076 1114
 			p_cell);
1077 1115
 		abort();
1078 1116
 	}
1117
+	/*
1079 1118
 	if (is_in_timer_list2(& p_cell->outbound_response.retr_timer )) {
1080 1119
 		LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and still on RETR (rep)\n",
1081 1120
 			p_cell);
... ...
@@ -1098,6 +1137,8 @@ void delete_cell( struct cell *p_cell )
1098 1137
 			abort();
1099 1138
 		}
1100 1139
 	}
1140
+	*/
1141
+	reset_retr_timers( hash_table, p_cell );
1101 1142
 #endif
1102 1143
 	/* still in use ... don't delete */
1103 1144
 	if ( T_IS_REFED(p_cell) ) {
... ...
@@ -1113,7 +1154,7 @@ void delete_cell( struct cell *p_cell )
1113 1154
 		/* it's added to del list for future del */
1114 1155
 		set_timer( hash_table, &(p_cell->dele_tl), DELETE_LIST );
1115 1156
 	} else {
1116
-		DBG("DEBUG: delete_handler : delete transaction %p\n", p_cell );
1157
+		DBG("DEBUG: delete transaction %p\n", p_cell );
1117 1158
 		free_cell( p_cell );
1118 1159
 	}
1119 1160
 }
... ...
@@ -1216,7 +1257,13 @@ void retransmission_handler( void *attr)
1216 1257
 
1217 1258
 	/* retransmision */
1218 1259
 	DBG("DEBUG: retransmission_handler : resending (t=%p)\n", r_buf->my_T);
1219
-	SEND_BUFFER( r_buf );
1260
+	if (r_buf->reply) {
1261
+		LOCK_REPLIES( r_buf->my_T );
1262
+		SEND_BUFFER( r_buf );
1263
+		UNLOCK_REPLIES( r_buf->my_T );
1264
+	} else {
1265
+		SEND_BUFFER( r_buf );
1266
+	}
1220 1267
 
1221 1268
 	id = r_buf->retr_list;
1222 1269
 	r_buf->retr_list = id < RT_T2 ? id + 1 : RT_T2;
... ...
@@ -1286,8 +1333,9 @@ void wait_handler( void *attr)
1286 1333
 	/* the cell is removed from the hash table */
1287 1334
 	DBG("DEBUG: wait_handler : removing %p from table \n", p_cell );
1288 1335
 	remove_from_hash_table( hash_table, p_cell );
1336
+	/* jku: no more here -- we do it when we put a transaction on wait */
1289 1337
 	DBG("DEBUG: wait_handler : stopping all timers\n");
1290
-	reset_retr_timers(hash_table,p_cell) ;
1338
+	reset_retr_timers(hash_table,p_cell) ; 
1291 1339
 	/* put it on DEL_LIST - sch for del */
1292 1340
 #ifdef EXTRA_DEBUG
1293 1341
 	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 117
 		DBG_REF("ref", (_T_cell));	})
113 118
 #endif
114 119
 
120
+enum addifnew_status { AIN_ERROR, AIN_RETR, AIN_NEW, AIN_NEWACK, AIN_OLDACK } ;
121
+
115 122
 
116 123
 int   tm_startup();
117 124
 void tm_shutdown();
... ...
@@ -121,7 +128,7 @@ void tm_shutdown();
121 128
  *       1 - a new transaction was created
122 129
  *      -1 - error, including retransmission
123 130
  */
124
-int  t_add_transaction( struct sip_msg* p_msg, char* foo, char* bar  );
131
+int  t_add_transaction( struct sip_msg* p_msg  );
125 132
 
126 133
 
127 134
 
... ...
@@ -149,7 +156,7 @@ int t_forward( struct sip_msg* p_msg , unsigned int dst_ip ,
149 156
  *       1 - forward successfull
150 157
  *      -1 - error during forward
151 158
  */
152
-int t_forward_uri( struct sip_msg* p_msg , char* foo, char* bar );
159
+int t_forward_uri( struct sip_msg* p_msg  );
153 160
 
154 161
 
155 162
 
... ...
@@ -194,7 +201,7 @@ int t_release_transaction( struct sip_msg* );
194 201
   * Returns  -1 -error
195 202
   *                1 - OK
196 203
   */
197
-int t_retransmit_reply( struct sip_msg *, char* , char* );
204
+int t_retransmit_reply( struct sip_msg *  );
198 205
 
199 206
 
200