... | ... |
@@ -54,7 +54,9 @@ ARCH = $(shell uname -m |sed -e s/i.86/i386/ -e s/sun4u/sparc64/ ) |
54 | 54 |
# issues additional debugging information if lock/unlock is called |
55 | 55 |
# -DFAST_LOCK |
56 | 56 |
# uses fast arhitecture specific locking (see the arh. specific section) |
57 |
-# |
|
57 |
+# -DNOISY_REPLIES |
|
58 |
+# turns on appending User-agent and Content-length:0 to ser-generated |
|
59 |
+# replies; |
|
58 | 60 |
# -DBUSY_WAIT |
59 | 61 |
# uses busy waiting on the lock |
60 | 62 |
# -DADAPTIVE_WAIT |
... | ... |
@@ -66,21 +68,27 @@ ARCH = $(shell uname -m |sed -e s/i.86/i386/ -e s/sun4u/sparc64/ ) |
66 | 68 |
# -DNOSMP |
67 | 69 |
# don't use smp compliant locking (faster but won't work on SMP machines) |
68 | 70 |
# (not yet enabled) |
71 |
+# -DWAIT |
|
72 |
+# protection against race condiditions; turn off only for debugging; |
|
73 |
+# to become non-optional if stable |
|
74 |
+# -DNEW_HNAME |
|
75 |
+# 32-bit header name parsing; turn off for lower speed ;-) or debugging; to become non-optional if fast and stable |
|
76 |
+# -DSRL Shortened Reply Lock -- moves more code, esp. "send" out |
|
77 |
+# of locks for greater speed; to become non-optional if fast and stable |
|
69 | 78 |
|
70 | 79 |
DEFS+= -DNAME='"$(NAME)"' -DVERSION='"$(RELEASE)"' -DARCH='"$(ARCH)"' \ |
71 | 80 |
-DOS='"$(OS)"' -DCOMPILER='"$(CC_VER)"'\ |
72 | 81 |
-DDNS_IP_HACK -DPKG_MALLOC -DSHM_MEM -DSHM_MMAP \ |
73 | 82 |
-DF_MALLOC -DUSE_SYNONIM\ |
74 | 83 |
-DNO_DEBUG \ |
84 |
+ -DWAIT -DNEW_HNAME -DNOISY_REPLIES -DSRL |
|
75 | 85 |
#-DADAPTIVE_WAIT -DADAPTIVE_WAIT_LOOPS=0 \ |
76 | 86 |
#-DNOSMP \ |
77 | 87 |
#-DEXTRA_DEBUG |
78 | 88 |
#-DVQ_MALLOC -DDBG_LOCK #-DSTATS |
79 | 89 |
#-DDBG_QM_MALLOC #-DNO_DEBUG |
80 |
-#-DEXTRA_DEBUG |
|
81 | 90 |
# -DUSE_SHM_MEM |
82 | 91 |
#-DNO_DEBUG |
83 |
-#-DPKG_MALLOC |
|
84 | 92 |
#-DNO_DEBUG#-DSTATS -DNO_DEBUG |
85 | 93 |
#-DNO_LOG |
86 | 94 |
|
... | ... |
@@ -235,7 +243,7 @@ ifeq ($(OS), SunOS) |
235 | 243 |
|
236 | 244 |
YACC=yacc |
237 | 245 |
LIBS+=-L/usr/local/lib -lxnet -lrt # or -lnsl -lsocket or -lglibc ? |
238 |
- # -lrt needed for sched_yield |
|
246 |
+ # -lrt needed for sched_yield; some systems may require -lposix4 |
|
239 | 247 |
endif |
240 | 248 |
|
241 | 249 |
ifeq ($(OS), FreeBSD) |
... | ... |
@@ -30,6 +30,7 @@ |
30 | 30 |
#endif |
31 | 31 |
#include "sr_module.h" |
32 | 32 |
#include "timer.h" |
33 |
+#include "msg_parser.h" |
|
33 | 34 |
|
34 | 35 |
|
35 | 36 |
#include <signal.h> |
... | ... |
@@ -126,6 +127,7 @@ Options:\n\ |
126 | 127 |
-h This help message\n\ |
127 | 128 |
-b nr Maximum receive buffer size which will not be exceeded by\n\ |
128 | 129 |
auto-probing procedure even if OS allows\n\ |
130 |
+ -m nr Size of shared memory allocated in Megabytes\n\ |
|
129 | 131 |
-w dir change the working directory to \"dir\" (default \"/\")\n\ |
130 | 132 |
-t dir chroot to \"dir\"\n\ |
131 | 133 |
-u uid change uid \n\ |
... | ... |
@@ -141,9 +143,11 @@ void print_ct_constants() |
141 | 143 |
#ifdef ADAPTIVE_WAIT |
142 | 144 |
printf("ADAPTIVE_WAIT_LOOPS=%d, ", ADAPTIVE_WAIT_LOOPS); |
143 | 145 |
#endif |
146 |
+/* |
|
144 | 147 |
#ifdef SHM_MEM |
145 | 148 |
printf("SHM_MEM_SIZE=%d, ", SHM_MEM_SIZE); |
146 | 149 |
#endif |
150 |
+*/ |
|
147 | 151 |
printf("MAX_RECV_BUFFER_SIZE %d, MAX_LISTEN %d," |
148 | 152 |
" MAX_URI_SIZE %d, MAX_PROCESSES %d\n", |
149 | 153 |
MAX_RECV_BUFFER_SIZE, MAX_LISTEN, MAX_URI_SIZE, MAX_PROCESSES ); |
... | ... |
@@ -204,6 +208,9 @@ process_bm_t process_bit = 0; |
204 | 208 |
/* cfg parsing */ |
205 | 209 |
int cfg_errors=0; |
206 | 210 |
|
211 |
+/* shared memory (in MB) */ |
|
212 |
+unsigned int shm_mem_size=SHM_MEM_SIZE * 1024 * 1024; |
|
213 |
+ |
|
207 | 214 |
#define MAX_FD 32 /* maximum number of inherited open file descriptors, |
208 | 215 |
(normally it shouldn't be bigger than 3) */ |
209 | 216 |
|
... | ... |
@@ -483,7 +490,7 @@ int main(int argc, char** argv) |
483 | 490 |
#ifdef STATS |
484 | 491 |
"s:" |
485 | 492 |
#endif |
486 |
- "f:p:b:l:n:rRvcdDEVhw:t:u:g:"; |
|
493 |
+ "f:p:m:b:l:n:rRvcdDEVhw:t:u:g:"; |
|
487 | 494 |
|
488 | 495 |
while((c=getopt(argc,argv,options))!=-1){ |
489 | 496 |
switch(c){ |
... | ... |
@@ -503,6 +510,15 @@ int main(int argc, char** argv) |
503 | 510 |
} |
504 | 511 |
break; |
505 | 512 |
|
513 |
+ case 'm': |
|
514 |
+ shm_mem_size=strtol(optarg, &tmp, 10) * 1024 * 1024; |
|
515 |
+ if (tmp &&(*tmp)){ |
|
516 |
+ fprintf(stderr, "bad shmem size number: -m %s\n", optarg); |
|
517 |
+ goto error; |
|
518 |
+ }; |
|
519 |
+ LOG(L_INFO, "ser: shared memory allocated: %d MByte\n", shm_mem_size ); |
|
520 |
+ break; |
|
521 |
+ |
|
506 | 522 |
case 'b': |
507 | 523 |
maxbuffer=strtol(optarg, &tmp, 10); |
508 | 524 |
if (tmp &&(*tmp)){ |
... | ... |
@@ -619,6 +635,10 @@ int main(int argc, char** argv) |
619 | 635 |
goto error; |
620 | 636 |
} |
621 | 637 |
|
638 |
+#ifdef NEW_HNAME |
|
639 |
+ init_htable(); |
|
640 |
+#endif |
|
641 |
+ |
|
622 | 642 |
/*init mallocs (before parsing cfg !)*/ |
623 | 643 |
if (init_mallocs()==-1) |
624 | 644 |
goto error; |
... | ... |
@@ -142,13 +142,13 @@ int shm_mem_init() |
142 | 142 |
strerror(errno)); |
143 | 143 |
return -1; |
144 | 144 |
} |
145 |
- shm_mempool=mmap(0, SHM_MEM_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, |
|
145 |
+ shm_mempool=mmap(0, /* SHM_MEM_SIZE */ shm_mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, |
|
146 | 146 |
fd ,0); |
147 | 147 |
/* close /dev/zero */ |
148 | 148 |
close(fd); |
149 | 149 |
#else |
150 | 150 |
|
151 |
- shm_shmid=shmget(IPC_PRIVATE, SHM_MEM_SIZE, 0700); |
|
151 |
+ shm_shmid=shmget(IPC_PRIVATE, /* SHM_MEM_SIZE */ shm_mem_size , 0700); |
|
152 | 152 |
if (shm_shmid==-1){ |
153 | 153 |
LOG(L_CRIT, "ERROR: shm_mem_init: could not allocate shared memory" |
154 | 154 |
" segment: %s\n", strerror(errno)); |
... | ... |
@@ -185,11 +185,11 @@ int shm_mem_init() |
185 | 185 |
#endif |
186 | 186 |
/* init it for malloc*/ |
187 | 187 |
# ifdef VQ_MALLOC |
188 |
- shm_block=vqm_malloc_init(shm_mempool, SHM_MEM_SIZE); |
|
188 |
+ shm_block=vqm_malloc_init(shm_mempool, /* SHM_MEM_SIZE */ shm_mem_size ); |
|
189 | 189 |
#elif defined F_MALLOC |
190 |
- shm_block=fm_malloc_init(shm_mempool, SHM_MEM_SIZE); |
|
190 |
+ shm_block=fm_malloc_init(shm_mempool, /* SHM_MEM_SIZE */ shm_mem_size ); |
|
191 | 191 |
# else |
192 |
- shm_block=qm_malloc_init(shm_mempool, SHM_MEM_SIZE); |
|
192 |
+ shm_block=qm_malloc_init(shm_mempool, /* SHM_MEM_SIZE */ shm_mem_size ); |
|
193 | 193 |
# endif |
194 | 194 |
if (shm_block==0){ |
195 | 195 |
LOG(L_CRIT, "ERROR: shm_mem_init: could not initialize shared" |
... | ... |
@@ -218,7 +218,7 @@ void shm_mem_destroy() |
218 | 218 |
DBG("shm_mem_destroy\n"); |
219 | 219 |
if (shm_mempool && (shm_mempool!=(void*)-1)) { |
220 | 220 |
#ifdef SHM_MMAP |
221 |
- munmap(shm_mempool, SHM_MEM_SIZE); |
|
221 |
+ munmap(shm_mempool, /* SHM_MEM_SIZE */ shm_mem_size ); |
|
222 | 222 |
#else |
223 | 223 |
shmdt(shm_mempool); |
224 | 224 |
#endif |
... | ... |
@@ -97,7 +97,13 @@ typedef struct cell |
97 | 97 |
/* protection against concurrent reply processing */ |
98 | 98 |
ser_lock_t reply_mutex; |
99 | 99 |
/* protection against concurrent ACK processing */ |
100 |
- ser_lock_t ack_mutex; |
|
100 |
+ ser_lock_t ack_mutex; |
|
101 |
+#ifdef WAIT |
|
102 |
+ /* protection against reentering WAIT state */ |
|
103 |
+ ser_lock_t wait_mutex; |
|
104 |
+ /* has the transaction been put on wait status ? */ |
|
105 |
+ int on_wait; |
|
106 |
+#endif |
|
101 | 107 |
|
102 | 108 |
/* this is where destination is stored for picked branch; |
103 | 109 |
good if a need to forward ACK later on */ |
... | ... |
@@ -111,6 +117,7 @@ typedef struct cell |
111 | 117 |
/* scheduled for deletion ? */ |
112 | 118 |
short damocles; |
113 | 119 |
#endif |
120 |
+ |
|
114 | 121 |
}cell_type; |
115 | 122 |
|
116 | 123 |
|
... | ... |
@@ -51,6 +51,9 @@ static int |
51 | 51 |
timer_semaphore=0, |
52 | 52 |
reply_semaphore=0, |
53 | 53 |
ack_semaphore=0; |
54 |
+#ifdef WAIT |
|
55 |
+static int wait_semaphore=0; |
|
56 |
+#endif |
|
54 | 57 |
/* and the maximum number of semaphores in the entry_semaphore set */ |
55 | 58 |
static int sem_nr; |
56 | 59 |
/* timer group locks */ |
... | ... |
@@ -166,6 +169,11 @@ again: |
166 | 169 |
semctl(reply_semaphore, 0 , IPC_RMID , 0 ); |
167 | 170 |
if (ack_semaphore>0) |
168 | 171 |
semctl(reply_semaphore, 0 , IPC_RMID , 0 ); |
172 |
+#ifdef WAIT |
|
173 |
+ if (wait_semaphore>0) |
|
174 |
+ semctl(wait_semaphore, 0 , IPC_RMID , 0 ); |
|
175 |
+#endif |
|
176 |
+ |
|
169 | 177 |
|
170 | 178 |
if (i==0){ |
171 | 179 |
LOG(L_CRIT, "lock_initialize: could not allocate semaphore" |
... | ... |
@@ -236,6 +244,23 @@ again: |
236 | 244 |
} |
237 | 245 |
} |
238 | 246 |
|
247 |
+#ifdef WAIT |
|
248 |
+ if ((wait_semaphore=init_semaphore_set(sem_nr))<0){ |
|
249 |
+ if (errno==EINVAL || errno==ENOSPC ) { |
|
250 |
+ DBG( "DEBUG:lock_initialize: wait semaphore initialization" |
|
251 |
+ " failure: %s\n", strerror(errno)); |
|
252 |
+ probe_run==1; |
|
253 |
+ i--; |
|
254 |
+ goto again; |
|
255 |
+ }else{ |
|
256 |
+ LOG(L_CRIT, "ERROR:lock_initialize: wait semaphore initialization" |
|
257 |
+ " failure: %s\n", strerror(errno)); |
|
258 |
+ goto error; |
|
259 |
+ } |
|
260 |
+ } |
|
261 |
+#endif |
|
262 |
+ |
|
263 |
+ |
|
239 | 264 |
|
240 | 265 |
|
241 | 266 |
/* return success */ |
... | ... |
@@ -280,8 +305,18 @@ void lock_cleanup() |
280 | 305 |
if (ack_semaphore > 0 && |
281 | 306 |
semctl( ack_semaphore, 0 , IPC_RMID , 0 )==-1) |
282 | 307 |
LOG(L_ERR, "ERROR: lock_cleanup, ack_semaphore cleanup failed\n"); |
308 |
+#ifdef WAIT |
|
309 |
+ if (wait_semaphore > 0 && |
|
310 |
+ semctl( wait_semaphore, 0 , IPC_RMID , 0 )==-1) |
|
311 |
+ LOG(L_ERR, "ERROR: lock_cleanup, wait_semaphore cleanup failed\n"); |
|
312 |
+#endif |
|
313 |
+ |
|
283 | 314 |
|
284 | 315 |
entry_semaphore = timer_semaphore = reply_semaphore = ack_semaphore = 0; |
316 |
+#ifdef WAIT |
|
317 |
+ wait_semaphore = 0; |
|
318 |
+#endif |
|
319 |
+ |
|
285 | 320 |
|
286 | 321 |
} |
287 | 322 |
#endif /*FAST_LOCK*/ |
... | ... |
@@ -329,13 +364,20 @@ int init_cell_lock( struct cell *cell ) |
329 | 364 |
#ifdef FAST_LOCK |
330 | 365 |
init_lock(cell->reply_mutex); |
331 | 366 |
init_lock(cell->ack_mutex); |
367 |
+#ifdef WAIT |
|
368 |
+ init_lock(cell->wait_mutex); |
|
369 |
+#endif |
|
332 | 370 |
return 0; |
333 | 371 |
#else |
334 | 372 |
cell->reply_mutex.semaphore_set=reply_semaphore; |
335 | 373 |
cell->reply_mutex.semaphore_index = cell->hash_index % sem_nr; |
336 | 374 |
cell->ack_mutex.semaphore_set=ack_semaphore; |
337 | 375 |
cell->ack_mutex.semaphore_index = cell->hash_index % sem_nr; |
338 |
-#endif |
|
376 |
+#ifdef WAIT |
|
377 |
+ cell->wait_mutex.semaphore_set=wait_semaphore; |
|
378 |
+ cell->wait_mutex.semaphore_index = cell->hash_index % sem_nr; |
|
379 |
+#endif /* WAIT */ |
|
380 |
+#endif /* FAST_LOCK */ |
|
339 | 381 |
return 0; |
340 | 382 |
} |
341 | 383 |
|
... | ... |
@@ -408,107 +408,6 @@ int t_forward_uri( struct sip_msg* p_msg ) |
408 | 408 |
#endif |
409 | 409 |
|
410 | 410 |
|
411 |
-/* This function is called whenever a reply for our module is received; |
|
412 |
- * we need to register this function on module initialization; |
|
413 |
- * Returns : 0 - core router stops |
|
414 |
- * 1 - core router relay statelessly |
|
415 |
- */ |
|
416 |
-int t_on_reply_received( struct sip_msg *p_msg ) |
|
417 |
-{ |
|
418 |
- unsigned int branch,len, msg_status, msg_class, save_clone; |
|
419 |
- struct sip_msg *clone, *backup; |
|
420 |
- int relay; |
|
421 |
- int start_fr; |
|
422 |
- int is_invite; |
|
423 |
- struct retrans_buff *rb; |
|
424 |
- |
|
425 |
- |
|
426 |
- /* make sure we know the assosociated tranaction ... */ |
|
427 |
- if (t_check( p_msg , &branch )==-1) return 1; |
|
428 |
- /* ... if there is no such, tell the core router to forward statelessly */ |
|
429 |
- if ( T<=0 ) return 1; |
|
430 |
- |
|
431 |
- DBG("DEBUG: t_on_reply_received: Original status =%d\n",T->status); |
|
432 |
- |
|
433 |
- /* it can take quite long -- better do it now than later |
|
434 |
- inside a reply_lock */ |
|
435 |
- if (!(clone=sip_msg_cloner( p_msg ))) { |
|
436 |
- goto error; |
|
437 |
- } |
|
438 |
- msg_status=p_msg->REPLY_STATUS; |
|
439 |
- msg_class=REPLY_CLASS(p_msg); |
|
440 |
- is_invite= T->inbound_request->REQ_METHOD==METHOD_INVITE; |
|
441 |
- |
|
442 |
- /* *** stop timers *** */ |
|
443 |
- rb=T->outbound_request[branch]; |
|
444 |
- /* stop retransmission */ |
|
445 |
- reset_timer( hash_table, &(rb->retr_timer)); |
|
446 |
- /* stop final response timer only if I got a final response */ |
|
447 |
- if ( msg_class>1 ) |
|
448 |
- reset_timer( hash_table, &(rb->fr_timer)); |
|
449 |
- |
|
450 |
- LOCK_REPLIES( T ); |
|
451 |
- /* if a got the first prov. response for an INVITE -> |
|
452 |
- change FR_TIME_OUT to INV_FR_TIME_UT */ |
|
453 |
- start_fr = !T->inbound_response[branch] && msg_class==1 && is_invite; |
|
454 |
- |
|
455 |
- /* *** store and relay message as needed *** */ |
|
456 |
- relay = t_should_relay_response( T , msg_status, branch, &save_clone ); |
|
457 |
- |
|
458 |
- if (save_clone) { |
|
459 |
- /* release previously hold message */ |
|
460 |
- backup = T->inbound_response[branch]; |
|
461 |
- T->inbound_response[branch] = clone; |
|
462 |
- T->tag=&(get_to(clone)->tag_value); |
|
463 |
- } else { |
|
464 |
- backup = NULL; |
|
465 |
- sip_msg_free( clone ); |
|
466 |
- } |
|
467 |
- |
|
468 |
- if (relay>=0 && push_reply_from_uac_to_uas( T, relay)==-1 ) { |
|
469 |
- /* restore original state first */ |
|
470 |
- if (save_clone) T->inbound_response[branch] = backup; |
|
471 |
- /* restart FR */ |
|
472 |
- start_fr=1; |
|
473 |
- goto cleanup; |
|
474 |
- } |
|
475 |
- |
|
476 |
- |
|
477 |
- /* *** ACK handling *** */ |
|
478 |
- if ( is_invite ) |
|
479 |
- { |
|
480 |
- if ( T->outbound_ack[branch] ) |
|
481 |
- { /*retransmit*/ |
|
482 |
- SEND_BUFFER( T->outbound_ack[branch] ); |
|
483 |
- } else if (msg_class>2 ) { /*on a non-200 reply to INVITE*/ |
|
484 |
- DBG("DEBUG: t_on_reply_received: >=3xx reply to INVITE: send ACK\n"); |
|
485 |
- if ( t_build_and_send_ACK( T , branch , p_msg )==-1) |
|
486 |
- { |
|
487 |
- LOG( L_ERR , "ERROR: t_on_reply_received: unable to send ACK\n" ); |
|
488 |
- /* restart FR */ |
|
489 |
- start_fr=1; |
|
490 |
- } |
|
491 |
- } |
|
492 |
- } |
|
493 |
-cleanup: |
|
494 |
- UNLOCK_REPLIES( T ); |
|
495 |
- if (backup) sip_msg_free(backup); |
|
496 |
- if (start_fr) set_timer( hash_table, &(rb->fr_timer), FR_INV_TIMER_LIST ); |
|
497 |
- /* restart retransmission if a provisional response came for |
|
498 |
- a non_INVITE -> retrasmit at RT_T2*/ |
|
499 |
- if ( msg_class==1 && !is_invite ) |
|
500 |
- { |
|
501 |
- rb->retr_list = RT_T2; |
|
502 |
- set_timer( hash_table, &(rb->retr_timer), RT_T2 ); |
|
503 |
- } |
|
504 |
-error: |
|
505 |
- T_UNREF( T ); |
|
506 |
- /* don't try to relay statelessly on error; on troubles, simply do nothing; |
|
507 |
- that will make the other party to retransmit; hopefuly, we'll then |
|
508 |
- be better off */ |
|
509 |
- return 0; |
|
510 |
-} |
|
511 |
- |
|
512 | 411 |
#ifdef _OBSOLETED_TM |
513 | 412 |
int t_on_request_received( struct sip_msg *p_msg , |
514 | 413 |
unsigned int ip , unsigned int port) |
... | ... |
@@ -612,30 +511,6 @@ int t_release_transaction( struct sip_msg* p_msg) |
612 | 511 |
|
613 | 512 |
|
614 | 513 |
|
615 |
-/* Retransmits the last sent inbound reply. |
|
616 |
- |
|
617 |
- * input: p_msg==request for which I want to retransmit an associated |
|
618 |
- reply |
|
619 |
- * Returns -1 -error |
|
620 |
- * 1 - OK |
|
621 |
- */ |
|
622 |
-int t_retransmit_reply( struct sip_msg* p_msg ) |
|
623 |
-{ |
|
624 |
-/* if (t_check( p_msg , 0 )==-1) return 1; */ |
|
625 |
- |
|
626 |
- /* if no transaction exists or no reply to be resend -> out */ |
|
627 |
-/* if ( T ) */ |
|
628 |
- { |
|
629 |
- LOCK_REPLIES( T ); |
|
630 |
- SEND_BUFFER( & T->outbound_response ); |
|
631 |
- UNLOCK_REPLIES( T ); |
|
632 |
- return 1; |
|
633 |
- } |
|
634 |
- |
|
635 |
- /* no transaction found */ |
|
636 |
-/* return -1; */ |
|
637 |
-} |
|
638 |
- |
|
639 | 514 |
|
640 | 515 |
|
641 | 516 |
|
... | ... |
@@ -651,170 +526,6 @@ int t_unref( /* struct sip_msg* p_msg */ ) |
651 | 526 |
|
652 | 527 |
|
653 | 528 |
|
654 |
-/* Force a new response into inbound response buffer. |
|
655 |
- * returns 1 if everything was OK or -1 for erro |
|
656 |
- */ |
|
657 |
-int t_send_reply( struct sip_msg* p_msg , unsigned int code , char * text ) |
|
658 |
-{ |
|
659 |
- unsigned int len, buf_len; |
|
660 |
- char * buf, *shbuf; |
|
661 |
- struct retrans_buff *rb; |
|
662 |
- |
|
663 |
- DBG("DEBUG: t_send_reply: entered\n"); |
|
664 |
- /* if (t_check( p_msg , 0 )==-1) return -1; |
|
665 |
- |
|
666 |
- if (!T) |
|
667 |
- { |
|
668 |
- LOG(L_ERR, "ERROR: t_send_reply: cannot send a t_reply to a message " |
|
669 |
- "for which no T-state has been established\n"); |
|
670 |
- return -1; |
|
671 |
- } |
|
672 |
- */ |
|
673 |
- |
|
674 |
- buf = build_res_buf_from_sip_req(code,text,0,0,T->inbound_request,&len); |
|
675 |
- DBG("DEBUG: t_send_reply: buffer computed\n"); |
|
676 |
- if (!buf) |
|
677 |
- { |
|
678 |
- DBG("DEBUG: t_send_reply: response building failed\n"); |
|
679 |
- goto error; |
|
680 |
- } |
|
681 |
- |
|
682 |
- LOCK_REPLIES( T ); |
|
683 |
- |
|
684 |
- rb = & T->outbound_response; |
|
685 |
- if (!rb->retr_buffer) { |
|
686 |
- /* initialize retransmission structure */ |
|
687 |
- memset( rb , 0 , sizeof (struct retrans_buff) ); |
|
688 |
- if (update_sock_struct_from_via( &(rb->to), p_msg->via1 )==-1) |
|
689 |
- { |
|
690 |
- LOG(L_ERR, "ERROR: t_send_reply: cannot lookup reply dst: %s\n", |
|
691 |
- p_msg->via1->host.s ); |
|
692 |
- goto error2; |
|
693 |
- } |
|
694 |
- |
|
695 |
- rb->retr_timer.tg=TG_RT; |
|
696 |
- rb->fr_timer.tg=TG_FR; |
|
697 |
- rb->retr_timer.payload = rb; |
|
698 |
- rb->fr_timer.payload = rb; |
|
699 |
- rb->to.sin_family = AF_INET; |
|
700 |
- rb->my_T = T; |
|
701 |
- rb->reply = code; |
|
702 |
- } |
|
703 |
- |
|
704 |
- |
|
705 |
- /* if this is a first reply (?100), longer replies will probably follow; |
|
706 |
- try avoiding shm_resize by higher buffer size */ |
|
707 |
- buf_len = rb->retr_buffer ? len : len + REPLY_OVERBUFFER_LEN; |
|
708 |
- |
|
709 |
- if (! (rb->retr_buffer = (char*)shm_resize( rb->retr_buffer, buf_len ))) |
|
710 |
- { |
|
711 |
- LOG(L_ERR, "ERROR: t_send_reply: cannot allocate shmem buffer\n"); |
|
712 |
- goto error2; |
|
713 |
- } |
|
714 |
- rb->bufflen = len ; |
|
715 |
- memcpy( rb->retr_buffer , buf , len ); |
|
716 |
- T->status = code; |
|
717 |
- SEND_BUFFER( rb ); |
|
718 |
- /* needs to be protected too because what timers are set depends |
|
719 |
- on current transactions status |
|
720 |
- */ |
|
721 |
- t_update_timers_after_sending_reply( rb ); |
|
722 |
- UNLOCK_REPLIES( T ); |
|
723 |
- |
|
724 |
- free( buf ) ; |
|
725 |
- /* start/stops the proper timers*/ |
|
726 |
- |
|
727 |
- DBG("DEBUG: t_send_reply: finished\n"); |
|
728 |
- |
|
729 |
- return 1; |
|
730 |
- |
|
731 |
-error2: |
|
732 |
- free ( buf ); |
|
733 |
-error: |
|
734 |
- return -1; |
|
735 |
-} |
|
736 |
- |
|
737 |
- |
|
738 |
- |
|
739 |
-/* Push a previously stored reply from UA Client to UA Server |
|
740 |
- * and send it out |
|
741 |
- */ |
|
742 |
-static int push_reply_from_uac_to_uas( struct cell* trans , unsigned int branch ) |
|
743 |
-{ |
|
744 |
- char *buf; |
|
745 |
- unsigned int len, buf_len; |
|
746 |
- struct retrans_buff *rb; |
|
747 |
- |
|
748 |
- DBG("DEBUG: push_reply_from_uac_to_uas: start\n"); |
|
749 |
- rb= & trans->outbound_response; |
|
750 |
- /* if there is a reply, release the buffer (everything else stays same) */ |
|
751 |
- if ( ! rb->retr_buffer ) { |
|
752 |
- /*init retrans buffer*/ |
|
753 |
- memset( rb , 0 , sizeof (struct retrans_buff) ); |
|
754 |
- if (update_sock_struct_from_via( &(rb->to), |
|
755 |
- trans->inbound_response[branch]->via2 )==-1) { |
|
756 |
- LOG(L_ERR, "ERROR: push_reply_from_uac_to_uas: " |
|
757 |
- "cannot lookup reply dst: %s\n", |
|
758 |
- trans->inbound_response[branch]->via2->host.s ); |
|
759 |
- goto error; |
|
760 |
- } |
|
761 |
- rb->retr_timer.tg=TG_RT; |
|
762 |
- rb->fr_timer.tg=TG_FR; |
|
763 |
- rb->retr_timer.payload = rb; |
|
764 |
- rb->fr_timer.payload = rb; |
|
765 |
- rb->to.sin_family = AF_INET; |
|
766 |
- rb->my_T = trans; |
|
767 |
- rb->reply = trans->inbound_response[branch]->REPLY_STATUS; |
|
768 |
- |
|
769 |
- } else { |
|
770 |
- reset_timer( hash_table, &(rb->retr_timer)); |
|
771 |
- reset_timer( hash_table, &(rb->fr_timer)); |
|
772 |
- } |
|
773 |
- |
|
774 |
- /* generate the retrans buffer */ |
|
775 |
- buf = build_res_buf_from_sip_res ( trans->inbound_response[branch], &len); |
|
776 |
- if (!buf) { |
|
777 |
- LOG(L_ERR, "ERROR: push_reply_from_uac_to_uas: " |
|
778 |
- "no shmem for outbound reply buffer\n"); |
|
779 |
- goto error; |
|
780 |
- } |
|
781 |
- |
|
782 |
- /* if this is a first reply (?100), longer replies will probably follow; |
|
783 |
- try avoiding shm_resize by higher buffer size */ |
|
784 |
- buf_len = rb->retr_buffer ? len : len + REPLY_OVERBUFFER_LEN; |
|
785 |
- if (! (rb->retr_buffer = (char*)shm_resize( rb->retr_buffer, buf_len ))) |
|
786 |
- { |
|
787 |
- LOG(L_ERR, "ERROR: t_send_reply: cannot allocate shmem buffer\n"); |
|
788 |
- goto error1; |
|
789 |
- } |
|
790 |
- rb->bufflen = len ; |
|
791 |
- memcpy( rb->retr_buffer , buf , len ); |
|
792 |
- free( buf ) ; |
|
793 |
- |
|
794 |
- /* update the status*/ |
|
795 |
- trans->status = trans->inbound_response[branch]->REPLY_STATUS; |
|
796 |
- if ( trans->inbound_response[branch]->REPLY_STATUS>=200 && |
|
797 |
- trans->relaied_reply_branch==-1 ) { |
|
798 |
- |
|
799 |
- memcpy( & trans->ack_to, & trans->outbound_request[ branch ]->to, |
|
800 |
- sizeof( struct sockaddr_in ) ); |
|
801 |
- trans->relaied_reply_branch = branch; |
|
802 |
- } |
|
803 |
- |
|
804 |
- /* start/stops the proper timers*/ |
|
805 |
- t_update_timers_after_sending_reply( rb ); |
|
806 |
- |
|
807 |
- /*send the reply*/ |
|
808 |
- SEND_BUFFER( rb ); |
|
809 |
- return 1; |
|
810 |
- |
|
811 |
-error1: |
|
812 |
- free( buf ); |
|
813 |
-error: |
|
814 |
- return -1; |
|
815 |
-} |
|
816 |
- |
|
817 |
- |
|
818 | 529 |
|
819 | 530 |
|
820 | 531 |
|
... | ... |
@@ -941,11 +652,30 @@ int t_put_on_wait( struct cell *Trans ) |
941 | 652 |
unsigned int i; |
942 | 653 |
struct retrans_buff* rb; |
943 | 654 |
|
655 |
+#ifndef WAIT |
|
944 | 656 |
if (is_in_timer_list2( &(Trans->wait_tl))) |
945 | 657 |
{ |
946 | 658 |
DBG("DEBUG: t_put_on_wait: already on wait\n"); |
947 | 659 |
return 1; |
948 | 660 |
} |
661 |
+#else |
|
662 |
+ /* have some race conditons occured and we already |
|
663 |
+ entered/passed the wait status previously? |
|
664 |
+ if so, exit now |
|
665 |
+ */ |
|
666 |
+ |
|
667 |
+ LOCK_WAIT(T); |
|
668 |
+ if (Trans->on_wait) |
|
669 |
+ { |
|
670 |
+ DBG("DEBUG: t_put_on_wait: already on wait\n"); |
|
671 |
+ UNLOCK_WAIT(T); |
|
672 |
+ return 1; |
|
673 |
+ } else { |
|
674 |
+ Trans->on_wait=1; |
|
675 |
+ UNLOCK_WAIT(T); |
|
676 |
+ }; |
|
677 |
+#endif |
|
678 |
+ |
|
949 | 679 |
|
950 | 680 |
/* remove from retranssmision and final response list */ |
951 | 681 |
DBG("DEBUG: t_put_on_wait: stopping timers (FR and RETR)\n"); |
... | ... |
@@ -1402,9 +1132,13 @@ void retransmission_handler( void *attr) |
1402 | 1132 |
/* retransmision */ |
1403 | 1133 |
DBG("DEBUG: retransmission_handler : resending (t=%p)\n", r_buf->my_T); |
1404 | 1134 |
if (r_buf->reply) { |
1135 |
+ T=r_buf->my_T; |
|
1136 |
+/* |
|
1405 | 1137 |
LOCK_REPLIES( r_buf->my_T ); |
1406 | 1138 |
SEND_BUFFER( r_buf ); |
1407 | 1139 |
UNLOCK_REPLIES( r_buf->my_T ); |
1140 |
+*/ |
|
1141 |
+ t_retransmit_reply(); |
|
1408 | 1142 |
}else{ |
1409 | 1143 |
SEND_BUFFER( r_buf ); |
1410 | 1144 |
} |
... | ... |
@@ -33,16 +33,35 @@ 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) ) |
|
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 |
+#define LOCK_WAIT(_t) lock(&(_t)->wait_mutex ) |
|
41 |
+#define UNLOCK_WAIT(_t) unlock(&(_t)->wait_mutex ) |
|
40 | 42 |
|
41 | 43 |
|
42 | 44 |
/* convenience short-cut macros */ |
43 | 45 |
#define REQ_METHOD first_line.u.request.method_value |
44 | 46 |
#define REPLY_STATUS first_line.u.reply.statuscode |
45 | 47 |
#define REPLY_CLASS(_reply) ((_reply)->REPLY_STATUS/100) |
48 |
+ |
|
49 |
+/* send a private buffer: utilize a retransmission structure |
|
50 |
+ but take a separate buffer not refered by it; healthy |
|
51 |
+ for reducing time spend in REPLIES locks |
|
52 |
+*/ |
|
53 |
+ |
|
54 |
+#define SEND_PR_BUFFER(_rb,_bf,_le ) ({ if ((_rb)->retr_buffer) \ |
|
55 |
+ { udp_send( (_bf), (_le), (struct sockaddr*)&((_rb)->to) , \ |
|
56 |
+ sizeof(struct sockaddr_in) ); \ |
|
57 |
+ } else { \ |
|
58 |
+ DBG("ERROR: attempt to send an empty buffer from %s (%d)", \ |
|
59 |
+ __FUNCTION__, __LINE__ ); }}) |
|
60 |
+ |
|
61 |
+#define SEND_BUFFER( _rb ) SEND_PR_BUFFER( \ |
|
62 |
+ _rb,(_rb)->retr_buffer, (_rb)->bufflen ) |
|
63 |
+ |
|
64 |
+/* |
|
46 | 65 |
#define SEND_BUFFER( _rb ) ({ if ((_rb)->retr_buffer) \ |
47 | 66 |
{ udp_send( (_rb)->retr_buffer, \ |
48 | 67 |
(_rb)->bufflen, (struct sockaddr*)&((_rb)->to) , \ |
... | ... |
@@ -50,6 +69,7 @@ extern struct s_table* hash_table; |
50 | 69 |
} else \ |
51 | 70 |
DBG("ERROR: attempt to send an empty buffer from %s (%d)", \ |
52 | 71 |
__FUNCTION__, __LINE__ ); }) |
72 |
+*/ |
|
53 | 73 |
|
54 | 74 |
|
55 | 75 |
/* |
... | ... |
@@ -165,7 +185,12 @@ int t_forward_uri( struct sip_msg* p_msg ); |
165 | 185 |
* Returns : 0 - core router stops |
166 | 186 |
* 1 - core router relay statelessly |
167 | 187 |
*/ |
188 |
+ |
|
189 |
+#ifdef SRL |
|
190 |
+int t_on_reply( struct sip_msg *p_msg ) ; |
|
191 |
+#else |
|
168 | 192 |
int t_on_reply_received( struct sip_msg *p_msg ) ; |
193 |
+#endif |
|
169 | 194 |
|
170 | 195 |
|
171 | 196 |
|
... | ... |
@@ -201,7 +226,7 @@ int t_release_transaction( struct sip_msg* ); |
201 | 226 |
* Returns -1 -error |
202 | 227 |
* 1 - OK |
203 | 228 |
*/ |
204 |
-int t_retransmit_reply( struct sip_msg * ); |
|
229 |
+int t_retransmit_reply( /* struct sip_msg * */ ); |
|
205 | 230 |
|
206 | 231 |
|
207 | 232 |
|
... | ... |
@@ -234,7 +259,14 @@ int t_should_relay_response( struct cell *Trans, int new_code, int branch, int * |
234 | 259 |
int t_update_timers_after_sending_reply( struct retrans_buff *rb ); |
235 | 260 |
int t_put_on_wait( struct cell *Trans ); |
236 | 261 |
int relay_lowest_reply_upstream( struct cell *Trans , struct sip_msg *p_msg ); |
262 |
+ |
|
263 |
+#ifdef SRL |
|
264 |
+static int push_reply( struct cell* trans , unsigned int branch , |
|
265 |
+ char *buf, unsigned int len); |
|
266 |
+#else |
|
237 | 267 |
static int push_reply_from_uac_to_uas( struct cell* Trans , unsigned int ); |
268 |
+#endif |
|
269 |
+ |
|
238 | 270 |
int add_branch_label( struct cell *Trans, struct sip_msg *p_msg , int branch ); |
239 | 271 |
int get_ip_and_port_from_uri( struct sip_msg* p_msg , unsigned int *param_ip, unsigned int *param_port); |
240 | 272 |
|
... | ... |
@@ -33,11 +33,11 @@ int t_forward_nonack( struct sip_msg* p_msg , unsigned int dest_ip_param , |
33 | 33 |
|
34 | 34 |
if ( T->outbound_request[branch]==NULL ) |
35 | 35 |
{ |
36 |
- DBG("DEBUG: t_forward: first time forwarding\n"); |
|
36 |
+ DBG("DEBUG: t_forward_nonack: first time forwarding\n"); |
|
37 | 37 |
/* special case : CANCEL */ |
38 | 38 |
if ( p_msg->REQ_METHOD==METHOD_CANCEL ) |
39 | 39 |
{ |
40 |
- DBG("DEBUG: t_forward: it's CANCEL\n"); |
|
40 |
+ DBG("DEBUG: t_forward_nonack: it's CANCEL\n"); |
|
41 | 41 |
/* find original cancelled transaction; if found, use its |
42 | 42 |
next-hops; otherwise use those passed by script */ |
43 | 43 |
if ( T->T_canceled==T_UNDEFINED ) |
... | ... |
@@ -48,7 +48,7 @@ int t_forward_nonack( struct sip_msg* p_msg , unsigned int dest_ip_param , |
48 | 48 |
/* if in 1xx status, send to the same destination */ |
49 | 49 |
if ( (T->T_canceled->status/100)==1 ) |
50 | 50 |
{ |
51 |
- DBG("DEBUG: t_forward: it's CANCEL and I will send " |
|
51 |
+ DBG("DEBUG: t_forward_nonack: it's CANCEL and I will send " |
|
52 | 52 |
"to the same place where INVITE went\n"); |
53 | 53 |
dest_ip=T->T_canceled->outbound_request[branch]-> |
54 | 54 |
to.sin_addr.s_addr; |
... | ... |
@@ -59,12 +59,12 @@ int t_forward_nonack( struct sip_msg* p_msg , unsigned int dest_ip_param , |
59 | 59 |
T->label = T->T_canceled->label; |
60 | 60 |
#endif |
61 | 61 |
} else { /* transaction exists, but nothing to cancel */ |
62 |
- DBG("DEBUG: t_forward: it's CANCEL but " |
|
62 |
+ DBG("DEBUG: t_forward_nonack: it's CANCEL but " |
|
63 | 63 |
"I have nothing to cancel here\n"); |
64 | 64 |
/* forward CANCEL as a stand-alone transaction */ |
65 | 65 |
} |
66 | 66 |
} else { /* transaction doesnot exists */ |
67 |
- DBG("DEBUG: t_forward: canceled request not found! " |
|
67 |
+ DBG("DEBUG: t_forward_nonack: canceled request not found! " |
|
68 | 68 |
"nothing to CANCEL\n"); |
69 | 69 |
} |
70 | 70 |
}/* end special case CANCEL*/ |
... | ... |
@@ -77,19 +77,19 @@ int t_forward_nonack( struct sip_msg* p_msg , unsigned int dest_ip_param , |
77 | 77 |
goto error; |
78 | 78 |
|
79 | 79 |
/* allocates a new retrans_buff for the outbound request */ |
80 |
- DBG("DEBUG: t_forward: building outbound request\n"); |
|
80 |
+ DBG("DEBUG: t_forward_nonack: building outbound request\n"); |
|
81 | 81 |
shm_lock(); |
82 | 82 |
rb = (struct retrans_buff*) shm_malloc_unsafe( sizeof(struct retrans_buff) ); |
83 | 83 |
if (!rb) |
84 | 84 |
{ |
85 |
- LOG(L_ERR, "ERROR: t_forward: out of shmem\n"); |
|
85 |
+ LOG(L_ERR, "ERROR: t_forward_nonack: out of shmem\n"); |
|
86 | 86 |
shm_unlock(); |
87 | 87 |
goto error; |
88 | 88 |
} |
89 | 89 |
shbuf = (char *) shm_malloc_unsafe( len ); |
90 | 90 |
if (!shbuf) |
91 | 91 |
{ |
92 |
- LOG(L_ERR, "ERROR: t_forward: out of shmem buffer\n"); |
|
92 |
+ LOG(L_ERR, "ERROR: t_forward_nonack: out of shmem buffer\n"); |
|
93 | 93 |
shm_unlock(); |
94 | 94 |
goto error; |
95 | 95 |
} |
... | ... |
@@ -114,9 +114,11 @@ int t_forward_nonack( struct sip_msg* p_msg , unsigned int dest_ip_param , |
114 | 114 |
/* link the retransmission buffer to our structures when the job is done */ |
115 | 115 |
free( buf ) ; buf=NULL; |
116 | 116 |
|
117 |
- DBG("DEBUG: t_forward: starting timers (retrans and FR) %d\n",get_ticks() ); |
|
117 |
+ DBG("DEBUG: t_forward_nonack: starting timers (retrans and FR) %d\n",get_ticks() ); |
|
118 | 118 |
/*sets and starts the FINAL RESPONSE timer */ |
119 |
+#ifdef FR |
|
119 | 120 |
set_timer( hash_table, &(rb->fr_timer), FR_TIMER_LIST ); |
121 |
+#endif |
|
120 | 122 |
|
121 | 123 |
/* sets and starts the RETRANS timer */ |
122 | 124 |
rb->retr_list = RT_T1_TO_1; |
... | ... |
@@ -132,12 +134,14 @@ int t_forward_nonack( struct sip_msg* p_msg , unsigned int dest_ip_param , |
132 | 134 |
|
133 | 135 |
if ( p_msg->REQ_METHOD==METHOD_CANCEL ) |
134 | 136 |
{ |
135 |
- DBG("DEBUG: t_forward: forwarding CANCEL\n"); |
|
137 |
+ DBG("DEBUG: t_forward_nonack: forwarding CANCEL\n"); |
|
136 | 138 |
/* if no transaction to CANCEL */ |
137 | 139 |
/* or if the canceled transaction has a final status -> drop the CANCEL*/ |
138 | 140 |
if ( T->T_canceled!=T_NULL && T->T_canceled->status>=200) |
139 | 141 |
{ |
142 |
+#ifdef FR |
|
140 | 143 |
reset_timer( hash_table, &(rb->fr_timer )); |
144 |
+#endif |
|
141 | 145 |
reset_timer( hash_table, &(rb->retr_timer )); |
142 | 146 |
return 1; |
143 | 147 |
} |
... | ... |
@@ -182,7 +186,7 @@ int t_forward_ack( struct sip_msg* p_msg , unsigned int dest_ip_param , |
182 | 186 |
return -1; |
183 | 187 |
} |
184 | 188 |
|
185 |
- DBG("DEBUG: t_forward: forwarding ACK [%d]\n",branch); |
|
189 |
+ DBG("DEBUG: t_forward_ack: forwarding ACK [%d]\n",branch); |
|
186 | 190 |
/* not able to build branch -- then better give up */ |
187 | 191 |
if ( add_branch_label( T, p_msg , branch )==-1) { |
188 | 192 |
LOG( L_ERR, "ERROR: t_forward_ack failed to add branch label\n" ); |
189 | 193 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,520 @@ |
1 |
+/* |
|
2 |
+ * $Id$ |
|
3 |
+ * |
|
4 |
+ */ |
|
5 |
+ |
|
6 |
+ |
|
7 |
+#include "hash_func.h" |
|
8 |
+#include "t_funcs.h" |
|
9 |
+#include "../../dprint.h" |
|
10 |
+#include "../../config.h" |
|
11 |
+#include "../../parser_f.h" |
|
12 |
+#include "../../ut.h" |
|
13 |
+#include "../../timer.h" |
|
14 |
+ |
|
15 |
+#ifndef SRL |
|
16 |
+/* This function is called whenever a reply for our module is received; |
|
17 |
+ * we need to register this function on module initialization; |
|
18 |
+ * Returns : 0 - core router stops |
|
19 |
+ * 1 - core router relay statelessly |
|
20 |
+ */ |
|
21 |
+int t_on_reply_received( struct sip_msg *p_msg ) |
|
22 |
+{ |
|
23 |
+ unsigned int branch,len, msg_status, msg_class, save_clone; |
|
24 |
+ struct sip_msg *clone, *backup; |
|
25 |
+ int relay; |
|
26 |
+ int start_fr; |
|
27 |
+ int is_invite; |
|
28 |
+ struct retrans_buff *rb; |
|
29 |
+ |
|
30 |
+ |
|
31 |
+ /* make sure we know the assosociated tranaction ... */ |
|
32 |
+ if (t_check( p_msg , &branch )==-1) return 1; |
|
33 |
+ /* ... if there is no such, tell the core router to forward statelessly */ |
|
34 |
+ if ( T<=0 ) return 1; |
|
35 |
+ |
|
36 |
+ DBG("DEBUG: t_on_reply_received: Original status =%d\n",T->status); |
|
37 |
+ |
|
38 |
+ /* it can take quite long -- better do it now than later |
|
39 |
+ inside a reply_lock */ |
|
40 |
+ if (!(clone=sip_msg_cloner( p_msg ))) { |
|
41 |
+ goto error; |
|
42 |
+ } |
|
43 |
+ msg_status=p_msg->REPLY_STATUS; |
|
44 |
+ msg_class=REPLY_CLASS(p_msg); |
|
45 |
+ is_invite= T->inbound_request->REQ_METHOD==METHOD_INVITE; |
|
46 |
+ |
|
47 |
+ /* *** stop timers *** */ |
|
48 |
+ rb=T->outbound_request[branch]; |
|
49 |
+ /* stop retransmission */ |
|
50 |
+ reset_timer( hash_table, &(rb->retr_timer)); |
|
51 |
+ /* stop final response timer only if I got a final response */ |
|
52 |
+ if ( msg_class>1 ) |
|
53 |
+ reset_timer( hash_table, &(rb->fr_timer)); |
|
54 |
+ |
|
55 |
+ LOCK_REPLIES( T ); |
|
56 |
+ /* if a got the first prov. response for an INVITE -> |
|
57 |
+ change FR_TIME_OUT to INV_FR_TIME_UT */ |
|
58 |
+ start_fr = !T->inbound_response[branch] && msg_class==1 && is_invite; |
|
59 |
+ |
|
60 |
+ /* *** store and relay message as needed *** */ |
|
61 |
+ relay = t_should_relay_response( T , msg_status, branch, &save_clone ); |
|
62 |
+ |
|
63 |
+ if (save_clone) { |
|
64 |
+ /* release previously hold message */ |
|
65 |
+ backup = T->inbound_response[branch]; |
|
66 |
+ T->inbound_response[branch] = clone; |
|
67 |
+ T->tag=&(get_to(clone)->tag_value); |
|
68 |
+ } else { |
|
69 |
+ backup = NULL; |
|
70 |
+ sip_msg_free( clone ); |
|
71 |
+ } |
|
72 |
+ |
|
73 |
+ if (relay>=0 && |
|
74 |
+ push_reply_from_uac_to_uas( T, relay ) == -1 ) { |
|
75 |
+ /* restore original state first */ |
|
76 |
+ if (save_clone) T->inbound_response[branch] = backup; |
|
77 |
+ /* restart FR */ |
|
78 |
+ start_fr=1; |
|
79 |
+ goto cleanup; |
|
80 |
+ } |
|
81 |
+ |
|
82 |
+ |
|
83 |
+ /* *** ACK handling *** */ |
|
84 |
+ if ( is_invite ) |
|
85 |
+ { |
|
86 |
+ if ( T->outbound_ack[branch] ) |
|
87 |
+ { /*retransmit*/ |
|
88 |
+ SEND_BUFFER( T->outbound_ack[branch] ); |
|
89 |
+ } else if (msg_class>2 ) { /*on a non-200 reply to INVITE*/ |
|
90 |
+ DBG("DEBUG: t_on_reply_received: >=3xx reply to INVITE: send ACK\n"); |
|
91 |
+ if ( t_build_and_send_ACK( T , branch , p_msg )==-1) |
|
92 |
+ { |
|
93 |
+ LOG( L_ERR , "ERROR: t_on_reply_received: unable to send ACK\n" ); |
|
94 |
+ /* restart FR */ |
|
95 |
+ start_fr=1; |
|
96 |
+ } |
|
97 |
+ } |
|
98 |
+ } |
|
99 |
+cleanup: |
|
100 |
+ UNLOCK_REPLIES( T ); |
|
101 |
+ if (backup) sip_msg_free(backup); |
|
102 |
+ if (start_fr) set_timer( hash_table, &(rb->fr_timer), FR_INV_TIMER_LIST ); |
|
103 |
+ /* restart retransmission if a provisional response came for |
|
104 |
+ a non_INVITE -> retrasmit at RT_T2*/ |
|
105 |
+ if ( msg_class==1 && !is_invite ) |
|
106 |
+ { |
|
107 |
+ rb->retr_list = RT_T2; |
|
108 |
+ set_timer( hash_table, &(rb->retr_timer), RT_T2 ); |
|
109 |
+ } |
|
110 |
+error: |
|
111 |
+ T_UNREF( T ); |
|
112 |
+ /* don't try to relay statelessly on error; on troubles, simply do nothing; |
|
113 |
+ that will make the other party to retransmit; hopefuly, we'll then |
|
114 |
+ be better off */ |
|
115 |
+ return 0; |
|
116 |
+} |
|
117 |
+#endif |
|
118 |
+ |
|
119 |
+ |
|
120 |
+ |
|
121 |
+/* Retransmits the last sent inbound reply. |
|
122 |
+ |
|
123 |
+ * input: p_msg==request for which I want to retransmit an associated |
|
124 |
+ reply |
|
125 |
+ * Returns -1 -error |
|
126 |
+ * 1 - OK |
|
127 |
+ */ |
|
128 |
+int t_retransmit_reply( /* struct sip_msg* p_msg */ ) |
|
129 |
+{ |
|
130 |
+ |
|
131 |
+#ifdef SRL |
|
132 |
+ void *b; |
|
133 |
+ int len; |
|
134 |
+#endif |
|
135 |
+ LOCK_REPLIES( T ); |
|
136 |
+ |
|
137 |
+#ifdef SRL |
|
138 |
+ if (!(b=pkg_malloc( len=T->outbound_response.bufflen ))) { |
|
139 |
+ UNLOCK_REPLIES( T ); |
|
140 |
+ return -1; |
|
141 |
+ }; |
|
142 |
+ memcpy( b, T->outbound_response.retr_buffer, len ); |
|
143 |
+#else |
|
144 |
+ SEND_BUFFER( & T->outbound_response ); |
|
145 |
+#endif |
|
146 |
+ UNLOCK_REPLIES( T ); |
|
147 |
+ |
|
148 |
+#ifdef SRL |
|
149 |
+ SEND_PR_BUFFER( & T->outbound_response, b, len ); |
|
150 |
+ pkg_free( b ); |
|
151 |
+#endif |
|
152 |
+ return 1; |
|
153 |
+} |
|
154 |
+ |
|
155 |
+/* Force a new response into inbound response buffer. |
|
156 |
+ * returns 1 if everything was OK or -1 for erro |
|
157 |
+ */ |
|
158 |
+int t_send_reply( struct sip_msg* p_msg , unsigned int code , char * text ) |
|
159 |
+{ |
|
160 |
+ unsigned int len, buf_len; |
|
161 |
+ char * buf, *shbuf; |
|
162 |
+ struct retrans_buff *rb; |
|
163 |
+ |
|
164 |
+ DBG("DEBUG: t_send_reply: entered\n"); |
|
165 |
+ |
|
166 |
+ buf = build_res_buf_from_sip_req(code,text,0,0,T->inbound_request,&len); |
|
167 |
+ DBG("DEBUG: t_send_reply: buffer computed\n"); |
|
168 |
+ if (!buf) |
|
169 |
+ { |
|
170 |
+ DBG("DEBUG: t_send_reply: response building failed\n"); |
|
171 |
+ goto error; |
|
172 |
+ } |
|
173 |
+ |
|
174 |
+ LOCK_REPLIES( T ); |
|
175 |
+ |
|
176 |
+ rb = & T->outbound_response; |
|
177 |
+ if (!rb->retr_buffer) { |
|
178 |
+ /* initialize retransmission structure */ |
|
179 |
+ memset( rb , 0 , sizeof (struct retrans_buff) ); |
|
180 |
+ if (update_sock_struct_from_via( &(rb->to), p_msg->via1 )==-1) |
|
181 |
+ { |
|
182 |
+ UNLOCK_REPLIES( T ); |
|
183 |
+ LOG(L_ERR, "ERROR: t_send_reply: cannot lookup reply dst: %s\n", |
|
184 |
+ p_msg->via1->host.s ); |
|
185 |
+ goto error2; |
|
186 |
+ } |
|
187 |
+ |
|
188 |
+ rb->retr_timer.tg=TG_RT; |
|
189 |
+ rb->fr_timer.tg=TG_FR; |
|
190 |
+ rb->retr_timer.payload = rb; |
|
191 |
+ rb->fr_timer.payload = rb; |
|
192 |
+ rb->to.sin_family = AF_INET; |
|
193 |
+ rb->my_T = T; |
|
194 |
+ rb->reply = code; |
|
195 |
+ } |
|
196 |
+ |
|
197 |
+ |
|
198 |
+ /* if this is a first reply (?100), longer replies will probably follow; |
|
199 |
+ try avoiding shm_resize by higher buffer size */ |
|
200 |
+ buf_len = rb->retr_buffer ? len : len + REPLY_OVERBUFFER_LEN; |
|
201 |
+ |
|
202 |
+ if (! (rb->retr_buffer = (char*)shm_resize( rb->retr_buffer, buf_len ))) |
|
203 |
+ { |
|
204 |
+ UNLOCK_REPLIES( T ); |
|
205 |
+ LOG(L_ERR, "ERROR: t_send_reply: cannot allocate shmem buffer\n"); |
|
206 |
+ goto error2; |
|
207 |
+ } |
|
208 |
+ rb->bufflen = len ; |
|
209 |
+ memcpy( rb->retr_buffer , buf , len ); |
|
210 |
+ T->status = code; |
|
211 |
+#ifndef SRL |
|
212 |
+ SEND_BUFFER( rb ); |
|
213 |
+#endif |
|
214 |
+ /* needs to be protected too because what timers are set depends |
|
215 |
+ on current transactions status |
|
216 |
+ */ |
|
217 |
+ t_update_timers_after_sending_reply( rb ); |
|
218 |
+ UNLOCK_REPLIES( T ); |
|
219 |
+ |
|
220 |
+#ifdef SRL |
|
221 |
+ SEND_PR_BUFFER( rb, buf, len ); |
|
222 |
+#endif |
|
223 |
+ |
|
224 |
+ free( buf ) ; |
|
225 |
+ /* start/stops the proper timers*/ |
|
226 |
+ |
|
227 |
+ DBG("DEBUG: t_send_reply: finished\n"); |
|
228 |
+ |
|
229 |
+ return 1; |
|
230 |
+ |
|
231 |
+error2: |
|
232 |
+ free ( buf ); |
|
233 |
+error: |
|
234 |
+ return -1; |
|
235 |
+} |
|
236 |
+ |
|
237 |
+ |
|
238 |
+ |
|
239 |
+ |
|
240 |
+/* Push a previously stored reply from UA Client to UA Server |
|
241 |
+ * and send it out |
|
242 |
+ */ |
|
243 |
+static int push_reply_from_uac_to_uas( struct cell* trans , unsigned int branch |
|
244 |
+#ifdef SRL |
|
245 |
+ , char *buf, unsigned int len |
|
246 |
+#endif |
|
247 |
+ ) |
|
248 |
+{ |
|
249 |
+ unsigned int buf_len; |
|
250 |
+ struct retrans_buff *rb; |
|
251 |
+#ifndef SRL |
|
252 |
+ char *buf; |
|
253 |
+ unsigned int len; |
|
254 |
+#endif |
|
255 |
+ |
|
256 |
+ DBG("DEBUG: push_reply_from_uac_to_uas: start\n"); |
|
257 |
+ rb= & trans->outbound_response; |
|
258 |
+ /* if there is a reply, release the buffer (everything else stays same) */ |
|
259 |
+ if ( ! rb->retr_buffer ) { |
|
260 |
+ /*init retrans buffer*/ |
|
261 |
+ memset( rb , 0 , sizeof (struct retrans_buff) ); |
|
262 |
+ if (update_sock_struct_from_via( &(rb->to), |
|
263 |
+ trans->inbound_response[branch]->via2 )==-1) { |
|
264 |
+ LOG(L_ERR, "ERROR: push_reply_from_uac_to_uas: " |
|
265 |
+ "cannot lookup reply dst: %s\n", |
|
266 |
+ trans->inbound_response[branch]->via2->host.s ); |
|
267 |
+ goto error; |
|
268 |
+ } |
|
269 |
+ rb->retr_timer.tg=TG_RT; |
|
270 |
+ rb->fr_timer.tg=TG_FR; |
|
271 |
+ rb->retr_timer.payload = rb; |
|
272 |
+ rb->fr_timer.payload = rb; |
|
273 |
+ rb->to.sin_family = AF_INET; |
|
274 |
+ rb->my_T = trans; |
|
275 |
+ rb->reply = trans->inbound_response[branch]->REPLY_STATUS; |
|
276 |
+ |
|
277 |
+ } else { |
|
278 |
+#ifndef SRL |
|
279 |
+ reset_timer( hash_table, &(rb->retr_timer)); |
|
280 |
+ reset_timer( hash_table, &(rb->fr_timer)); |
|
281 |
+#endif |
|
282 |
+ } |
|
283 |
+ |
|
284 |
+#ifndef SRL |
|
285 |
+ /* generate the retrans buffer */ |
|
286 |
+ buf = build_res_buf_from_sip_res ( trans->inbound_response[branch], &len); |
|
287 |
+ if (!buf) { |
|
288 |
+ LOG(L_ERR, "ERROR: push_reply_from_uac_to_uas: " |
|
289 |
+ "no shmem for outbound reply buffer\n"); |
|
290 |
+ goto error; |
|
291 |
+ } |
|
292 |
+#endif |
|
293 |
+ |
|
294 |
+ /* if this is a first reply (?100), longer replies will probably follow; |
|
295 |
+ try avoiding shm_resize by higher buffer size */ |
|
296 |
+ buf_len = rb->retr_buffer ? len : len + REPLY_OVERBUFFER_LEN; |
|
297 |
+ if (! (rb->retr_buffer = (char*)shm_resize( rb->retr_buffer, buf_len ))) |
|
298 |
+ { |
|
299 |
+ LOG(L_ERR, "ERROR: t_push: cannot allocate shmem buffer\n"); |
|
300 |
+ goto error1; |
|
301 |
+ } |
|
302 |
+ rb->bufflen = len ; |
|
303 |
+ memcpy( rb->retr_buffer , buf , len ); |
|
304 |
+#ifndef SRL |
|
305 |
+ free( buf ) ; |
|
306 |
+#endif |
|
307 |
+ |
|
308 |
+ /* update the status*/ |
|
309 |
+ trans->status = trans->inbound_response[branch]->REPLY_STATUS; |
|
310 |
+ if ( trans->inbound_response[branch]->REPLY_STATUS>=200 && |
|
311 |
+ trans->relaied_reply_branch==-1 ) { |
|
312 |
+ |
|
313 |
+ memcpy( & trans->ack_to, & trans->outbound_request[ branch ]->to, |
|
314 |
+ sizeof( struct sockaddr_in ) ); |
|
315 |
+ trans->relaied_reply_branch = branch; |
|
316 |
+ } |
|
317 |
+ |
|
318 |
+#ifndef SRL |
|
319 |
+ /* start/stops the proper timers*/ |
|
320 |
+ t_update_timers_after_sending_reply( rb ); |
|
321 |
+#endif |
|
322 |
+ |
|
323 |
+ /*send the reply*/ |
|
324 |
+ SEND_BUFFER( rb ); |
|
325 |
+ return 1; |
|
326 |
+ |
|
327 |
+error1: |
|
328 |
+#ifndef SRL |
|
329 |
+ free( buf ); |
|
330 |
+#endif |
|
331 |
+error: |
|
332 |
+ return -1; |
|
333 |
+} |
|
334 |
+ |
|
335 |
+/* Push a previously stored reply from UA Client to UA Server |
|
336 |
+ * and send it out |
|
337 |
+ */ |
|
338 |
+static int push_reply( struct cell* trans , unsigned int branch , |
|
339 |
+ char *buf, unsigned int len) |
|
340 |
+{ |
|
341 |
+ unsigned int buf_len; |
|
342 |
+ struct retrans_buff *rb; |
|
343 |
+ |
|
344 |
+ DBG("DEBUG: push_reply_from_uac_to_uas: start\n"); |
|
345 |
+ rb= & trans->outbound_response; |
|
346 |
+ /* if there is a reply, release the buffer (everything else stays same) */ |
|
347 |
+ if ( ! rb->retr_buffer ) { |
|
348 |
+ /*init retrans buffer*/ |
|
349 |
+ memset( rb , 0 , sizeof (struct retrans_buff) ); |
|
350 |
+ if (update_sock_struct_from_via( &(rb->to), |
|
351 |
+ trans->inbound_response[branch]->via2 )==-1) { |
|
352 |
+ LOG(L_ERR, "ERROR: push_reply_from_uac_to_uas: " |
|
353 |
+ "cannot lookup reply dst: %s\n", |
|
354 |
+ trans->inbound_response[branch]->via2->host.s ); |
|
355 |
+ goto error; |
|
356 |
+ } |
|
357 |
+ rb->retr_timer.tg=TG_RT; |
|
358 |
+ rb->fr_timer.tg=TG_FR; |
|
359 |
+ rb->retr_timer.payload = rb; |
|
360 |
+ rb->fr_timer.payload = rb; |
|
361 |
+ rb->to.sin_family = AF_INET; |
|
362 |
+ rb->my_T = trans; |
|
363 |
+ rb->reply = trans->inbound_response[branch]->REPLY_STATUS; |
|
364 |
+ }; |
|
365 |
+ |
|
366 |
+ /* if this is a first reply (?100), longer replies will probably follow; |
|
367 |
+ try avoiding shm_resize by higher buffer size */ |
|
368 |
+ buf_len = rb->retr_buffer ? len : len + REPLY_OVERBUFFER_LEN; |
|
369 |
+ if (! (rb->retr_buffer = (char*)shm_resize( rb->retr_buffer, buf_len ))) |
|
370 |
+ { |
|
371 |
+ LOG(L_ERR, "ERROR: t_push: cannot allocate shmem buffer\n"); |
|
372 |
+ goto error1; |
|
373 |
+ } |
|
374 |
+ rb->bufflen = len ; |
|
375 |
+ memcpy( rb->retr_buffer , buf , len ); |
|
376 |
+ |
|
377 |
+ /* update the status*/ |
|
378 |
+ trans->status = trans->inbound_response[branch]->REPLY_STATUS; |
|
379 |
+ if ( trans->inbound_response[branch]->REPLY_STATUS>=200 && |
|
380 |
+ trans->relaied_reply_branch==-1 ) { |
|
381 |
+ |
|
382 |
+ memcpy( & trans->ack_to, & trans->outbound_request[ branch ]->to, |
|
383 |
+ sizeof( struct sockaddr_in ) ); |
|
384 |
+ trans->relaied_reply_branch = branch; |
|
385 |
+ } |
|
386 |
+ |
|
387 |
+ /*send the reply*/ |
|
388 |
+ SEND_BUFFER( rb ); |
|
389 |
+ return 1; |
|
390 |
+ |
|
391 |
+error1: |
|
392 |
+error: |
|
393 |
+ return -1; |
|
394 |
+} |
|
395 |
+ |
|
396 |
+#ifdef SRL |
|
397 |
+/* This function is called whenever a reply for our module is received; |
|
398 |
+ * we need to register this function on module initialization; |
|
399 |
+ * Returns : 0 - core router stops |
|
400 |
+ * 1 - core router relay statelessly |
|
401 |
+ */ |
|
402 |
+int t_on_reply( struct sip_msg *p_msg ) |
|
403 |
+{ |
|
404 |
+ unsigned int branch,len, msg_status, msg_class, save_clone; |
|
405 |
+ struct sip_msg *clone, *backup; |
|
406 |
+ int relay; |
|
407 |
+ int start_fr; |
|
408 |
+ int is_invite; |
|
409 |
+ struct retrans_buff *rb; |
|
410 |
+ char *buf; |
|
411 |
+ unsigned int buf_len; |
|
412 |
+ |
|
413 |
+ |
|
414 |
+ /* make sure we know the assosociated tranaction ... */ |
|
415 |
+ if (t_check( p_msg , &branch )==-1) return 1; |
|
416 |
+ /* ... if there is no such, tell the core router to forward statelessly */ |
|
417 |
+ if ( T<=0 ) return 1; |
|
418 |
+ |
|
419 |
+ DBG("DEBUG: t_on_reply_received: Original status =%d\n",T->status); |
|
420 |
+ |
|
421 |
+ /* it can take quite long -- better do it now than later |
|
422 |
+ inside a reply_lock */ |
|
423 |
+ if (!(clone=sip_msg_cloner( p_msg ))) { |
|
424 |
+ goto error; |
|
425 |
+ } |
|
426 |
+ msg_status=p_msg->REPLY_STATUS; |
|
427 |
+ msg_class=REPLY_CLASS(p_msg); |
|
428 |
+ is_invite= T->inbound_request->REQ_METHOD==METHOD_INVITE; |
|
429 |
+ |
|
430 |
+ /* generate the retrans buffer, make a simplified |
|
431 |
+ assumption everything but 100 will be fwd-ed; |
|
432 |
+ sometimes it will result in useless CPU cycles |
|
433 |
+ but mostly the assumption holds and allows the |
|
434 |
+ work to be done out of criticial lock region |
|
435 |
+ */ |
|
436 |
+ if (msg_status==100) buf=0; |
|
437 |
+ else { |
|
438 |
+ buf = build_res_buf_from_sip_res ( p_msg, &buf_len); |
|
439 |
+ if (!buf) { |
|
440 |
+ LOG(L_ERR, "ERROR: t_on_reply_received: " |
|
441 |
+ "no mem for outbound reply buffer\n"); |
|
442 |
+ sip_msg_free( clone ); |
|
443 |
+ goto error; |
|
444 |
+ } |
|
445 |
+ } |
|
446 |
+ |
|
447 |
+ /* *** stop timers *** */ |
|
448 |
+ rb=T->outbound_request[branch]; |
|
449 |
+ /* stop retransmission */ |
|
450 |
+ reset_timer( hash_table, &(rb->retr_timer)); |
|
451 |
+ /* stop final response timer only if I got a final response */ |
|
452 |
+ if ( msg_class>1 ) |
|
453 |
+ reset_timer( hash_table, &(rb->fr_timer)); |
|
454 |
+ |
|
455 |
+ LOCK_REPLIES( T ); |
|
456 |
+ /* if a got the first prov. response for an INVITE -> |
|
457 |
+ change FR_TIME_OUT to INV_FR_TIME_UT */ |
|
458 |
+ start_fr = !T->inbound_response[branch] && msg_class==1 && is_invite; |
|
459 |
+ |
|
460 |
+ /* *** store and relay message as needed *** */ |
|
461 |
+ relay = t_should_relay_response( T , msg_status, branch, &save_clone ); |
|
462 |
+ |
|
463 |
+ if (save_clone) { |
|
464 |
+ /* release previously hold message */ |
|
465 |
+ backup = T->inbound_response[branch]; |
|
466 |
+ T->inbound_response[branch] = clone; |
|
467 |
+ T->tag=&(get_to(clone)->tag_value); |
|
468 |
+ } else { |
|
469 |
+ backup = NULL; |
|
470 |
+ sip_msg_free( clone ); |
|
471 |
+ } |
|
472 |
+ |
|
473 |
+ if (relay>=0 && |
|
474 |
+ push_reply( T, relay , buf, buf_len ) == -1 ) { |
|
475 |
+ /* restore original state first */ |
|
476 |
+ if (save_clone) T->inbound_response[branch] = backup; |
|
477 |
+ /* restart FR */ |
|
478 |
+ start_fr=1; |
|
479 |
+ goto cleanup; |
|
480 |
+ } |
|
481 |
+ |
|
482 |
+ |
|
483 |
+ /* *** ACK handling *** */ |
|
484 |
+ if ( is_invite ) |
|
485 |
+ { |
|
486 |
+ if ( T->outbound_ack[branch] ) |
|
487 |
+ { /*retransmit*/ |
|
488 |
+ SEND_BUFFER( T->outbound_ack[branch] ); |
|
489 |
+ } else if (msg_class>2 ) { /*on a non-200 reply to INVITE*/ |
|
490 |
+ DBG("DEBUG: t_on_reply_received: >=3xx reply to INVITE: send ACK\n"); |
|
491 |
+ if ( t_build_and_send_ACK( T , branch , p_msg )==-1) |
|
492 |
+ { |
|
493 |
+ LOG( L_ERR , "ERROR: t_on_reply_received: unable to send ACK\n" ); |
|
494 |
+ /* restart FR */ |
|
495 |
+ start_fr=1; |
|
496 |
+ } |
|
497 |
+ } |
|
498 |
+ } |
|
499 |
+cleanup: |
|
500 |
+ UNLOCK_REPLIES( T ); |
|
501 |
+ if (backup) sip_msg_free(backup); |
|
502 |
+ if (buf) free( buf ); |
|
503 |
+ t_update_timers_after_sending_reply( rb ); |
|
504 |
+ if (start_fr) set_timer( hash_table, &(rb->fr_timer), FR_INV_TIMER_LIST ); |
|
505 |
+ /* restart retransmission if a provisional response came for |
|
506 |
+ a non_INVITE -> retrasmit at RT_T2*/ |
|
507 |
+ if ( msg_class==1 && !is_invite ) |
|
508 |
+ { |
|
509 |
+ rb->retr_list = RT_T2; |
|
510 |
+ set_timer( hash_table, &(rb->retr_timer), RT_T2 ); |
|
511 |
+ } |
|
512 |
+error: |
|
513 |
+ T_UNREF( T ); |
|
514 |
+ /* don't try to relay statelessly on error; on troubles, simply do nothing; |
|
515 |
+ that will make the other party to retransmit; hopefuly, we'll then |
|
516 |
+ be better off */ |
|
517 |
+ return 0; |
|
518 |
+} |
|
519 |
+ |
|
520 |
+#endif |
... | ... |
@@ -46,6 +46,16 @@ void print_timer_list(struct s_table* hash_table, enum lists list_id) |
46 | 46 |
/* static void remove_from_timer_list_dummy( struct timer_link* tl ) */ |
47 | 47 |
void remove_timer_unsafe( struct timer_link* tl ) |
48 | 48 |
{ |
49 |
+#ifdef EXTRA_DEBUG |
|
50 |
+ if (tl && tl->timer_list && |
|
51 |
+ tl->timer_list->last_tl.prev_tl==0) { |
|
52 |
+ LOG( L_CRIT, |
|
53 |
+ "CRITICAL : Oh no, zero link in trailing timer element\n"); |
|
54 |
+ abort(); |
|
55 |
+ }; |
|
56 |
+#endif |
|
57 |
+ |
|
58 |
+ |
|
49 | 59 |
if (is_in_timer_list2( tl )) { |
50 | 60 |
tl->prev_tl->next_tl = tl->next_tl; |
51 | 61 |
tl->next_tl->prev_tl = tl->prev_tl; |
... | ... |
@@ -61,6 +71,14 @@ void remove_timer_unsafe( struct timer_link* tl ) |
61 | 71 |
void add_timer_unsafe( struct timer *timer_list, |
62 | 72 |
struct timer_link *tl, unsigned int time_out ) |
63 | 73 |
{ |
74 |
+#ifdef EXTRA_DEBUG |
|
75 |
+ if (timer_list->last_tl.prev_tl==0) { |
|
76 |
+ LOG( L_CRIT, |
|
77 |
+ "CRITICAL : Oh no, zero link in trailing timer element\n"); |
|
78 |
+ abort(); |
|
79 |
+ }; |
|
80 |
+#endif |
|
81 |
+ |
|
64 | 82 |
/* remove_from_timer_list( tl ); */ |
65 | 83 |
/* the entire timer list is locked now -- noone else can manipulate it */ |
66 | 84 |
/* lock( timer_list->mutex ); */ |
... | ... |
@@ -116,6 +134,14 @@ struct timer_link *check_and_split_time_list( struct timer *timer_list, int tim |
116 | 134 |
timer_list->first_tl.next_tl = tl; |
117 | 135 |
tl->prev_tl = & timer_list->first_tl; |
118 | 136 |
} |
137 |
+#ifdef EXTRA_DEBUG |
|
138 |
+ if (timer_list->last_tl.prev_tl==0) { |
|
139 |
+ LOG( L_CRIT, |
|
140 |
+ "CRITICAL : Oh no, zero link in trailing timer element\n"); |
|
141 |
+ abort(); |
|
142 |
+ }; |
|
143 |
+#endif |
|
144 |
+ |
|
119 | 145 |
|
120 | 146 |
/* give the list lock away */ |
121 | 147 |
unlock(timer_list->mutex); |
... | ... |
@@ -129,7 +129,11 @@ static struct module_exports nm_exports= { |
129 | 129 |
#else |
130 | 130 |
10, |
131 | 131 |
#endif |
132 |
+#ifdef SRL |
|
133 |
+ (response_function) t_on_reply, |
|
134 |
+#else |
|
132 | 135 |
(response_function) t_on_reply_received, |
136 |
+#endif |
|
133 | 137 |
(destroy_function) tm_shutdown, |
134 | 138 |
w_onbreak |
135 | 139 |
}; |
... | ... |
@@ -358,7 +362,7 @@ static int w_t_unref( struct sip_msg* p_msg, char* foo, char* bar ) |
358 | 362 |
static w_t_retransmit_reply( struct sip_msg* p_msg, char* foo, char* bar ) |
359 | 363 |
{ |
360 | 364 |
if (t_check( p_msg , 0 )==-1) return 1; |
361 |
- if (T) return t_retransmit_reply( p_msg ); |
|
365 |
+ if (T) return t_retransmit_reply( /* p_msg */ ); |
|
362 | 366 |
else return -1; |
363 | 367 |
} |
364 | 368 |
|