Browse code

sorry -- I'm taking off in few minutes and wanted to commit not to road-block dependent work -- I will post on that and provide history of changes when I'm back

Jiri Kuthan authored on 06/03/2003 17:43:17
Showing 22 changed files
... ...
@@ -18,7 +18,7 @@ auto_gen=lex.yy.c cfg.tab.c   #lexx, yacc etc
18 18
 #include  source related defs
19 19
 include Makefile.sources
20 20
 
21
-override exclude_modules:=CVS cpl cpl-c ext radius_acc radius_auth snmp \
21
+override exclude_modules:=CVS cpl cpl-c ext radius_acc radius_auth snmp jabber sms pa extcmd msilo auth \
22 22
 	$(exclude_modules)
23 23
 static_modules=
24 24
 static_modules_path=$(addprefix modules/, $(static_modules))
... ...
@@ -175,8 +175,6 @@ DEFS+= -DNAME='"$(NAME)"' -DVERSION='"$(RELEASE)"' -DARCH='"$(ARCH)"' \
175 175
 	 -DADAPTIVE_WAIT -DADAPTIVE_WAIT_LOOPS=1024 \
176 176
 	 -DDNS_IP_HACK \
177 177
 	 -DUSE_IPV6 \
178
-	 -DVOICE_MAIL \
179
-	 -D_TOTAG \
180 178
 	 -DUSE_TCP \
181 179
 	 -DDISABLE_NAGLE \
182 180
 	 -DDIGEST_DOMAIN \
... ...
@@ -197,7 +195,7 @@ DEFS+= -DNAME='"$(NAME)"' -DVERSION='"$(RELEASE)"' -DARCH='"$(ARCH)"' \
197 195
 	 #-DNO_LOG
198 196
 
199 197
 #PROFILE=  -pg #set this if you want profiling
200
-#mode = debug
198
+mode = debug
201 199
 ifeq ($(mode),)
202 200
 	mode = release
203 201
 endif
... ...
@@ -55,7 +55,7 @@ else
55 55
 fi
56 56
 # address of user wishing to initiate conversation
57 57
 if [ -z "$1" ] ; then
58
-	URI="sip:113311@192.168.2.16"
58
+	URI="sip:44@192.168.2.16"
59 59
 	echo "caller unspecified -- taking default value $URI"
60 60
 else
61 61
 	URI="$1"
... ...
@@ -43,12 +43,26 @@
43 43
 #include "t_cancel.h"
44 44
 #include "t_stats.h"
45 45
 
46
+static enum kill_reason kr;
47
+
46 48
 /* pointer to the big table where all the transaction data
47 49
    lives
48 50
 */
49 51
 
50 52
 static struct s_table*  tm_table;
51 53
 
54
+void set_kr( enum kill_reason _kr )
55
+{
56
+	if (kr!=0 && _kr!=0) {
57
+			DBG("DEBUG: set_kr: kill reason reset: "
58
+					"old=%d update=%d\n", kr, _kr );
59
+	}
60
+	kr|=_kr;
61
+}
62
+enum kill_reason get_kr() {
63
+	return kr;
64
+}
65
+
52 66
 void lock_hash(int i) 
53 67
 {
54 68
 	lock(&tm_table->entrys[i].mutex);
... ...
@@ -84,6 +98,7 @@ void free_cell( struct cell* dead_cell )
84 98
 	char *b;
85 99
 	int i;
86 100
 	struct sip_msg *rpl;
101
+	struct totag_elem *tt, *foo;
87 102
 
88 103
 	release_cell_lock( dead_cell );
89 104
 	shm_lock();
... ...
@@ -116,6 +131,15 @@ void free_cell( struct cell* dead_cell )
116 131
 		}
117 132
 	}
118 133
 
134
+	/* collected to tags */
135
+	tt=dead_cell->fwded_totags;
136
+	while(tt) {
137
+		foo=tt->next;
138
+		shm_free_unsafe(tt->tag.s);
139
+		shm_free_unsafe(tt);
140
+		tt=foo;
141
+	}
142
+
119 143
 	/* the cell's body */
120 144
 	shm_free_unsafe( dead_cell );
121 145
 
... ...
@@ -158,6 +182,9 @@ struct cell*  build_cell( struct sip_msg* p_msg )
158 182
 	/*fprintf(stderr,"before clone VIA |%.*s|\n",via_len(p_msg->via1),
159 183
 		via_s(p_msg->via1,p_msg));*/
160 184
 
185
+	callback_event(TMCB_REQUEST_IN, new_cell, p_msg, 
186
+			p_msg ? p_msg->REQ_METHOD : METHOD_UNDEF );
187
+
161 188
 	if (p_msg) {
162 189
 		new_cell->uas.request = sip_msg_cloner(p_msg);
163 190
 		if (!new_cell->uas.request)
... ...
@@ -120,10 +120,16 @@ typedef struct ua_server
120 120
 	struct sip_msg   *request;
121 121
 	struct retr_buf  response;
122 122
 	unsigned int     status;
123
+	/* keep to-tags for local 200 replies for INVITE -- 
124
+	 * we need them for dialog-wise matching of ACKs;
125
+	 * the pointer shows to shmem-ed reply */
126
+	str				 local_totag;
123 127
 #ifdef _TOTAG
124 128
 	str              to_tag;
125 129
 #endif
130
+#ifdef _OBSO
126 131
 	unsigned int     isACKed;
132
+#endif
127 133
 }ua_server_type;
128 134
 
129 135
 
... ...
@@ -151,6 +157,11 @@ typedef struct ua_client
151 157
 }ua_client_type;
152 158
 
153 159
 
160
+struct totag_elem {
161
+	str tag;
162
+	short acked;
163
+	struct totag_elem *next;
164
+};
154 165
 
155 166
 /* transaction context */
156 167
 
... ...
@@ -205,7 +216,8 @@ typedef struct cell
205 216
 
206 217
 	/* number of forks */
207 218
 	int nr_of_outgoings;
208
-	/* nr of replied branch */
219
+	/* nr of replied branch; 0..MAX_BRANCHES=branch value,
220
+	 * -1 no reply, -2 local reply */
209 221
 	int relaied_reply_branch;
210 222
 	/* UA Server */
211 223
 	struct ua_server  uas;
... ...
@@ -221,16 +233,9 @@ typedef struct cell
221 233
 	   dropping when C timer hits
222 234
 	*/
223 235
 	int noisy_ctimer;
224
-	/* is it a local transaction ? */
236
+	/* is it a local UAC transaction ? */
225 237
 	int local;
226 238
 
227
-#ifdef _XWAIT
228
-	/* protection against reentering WAIT state */
229
-	ser_lock_t	wait_mutex;
230
-	/* has the transaction been put on wait status ? */
231
-	int on_wait;
232
-#endif
233
-
234 239
 	/* MD5checksum  (meaningful only if syn_branch=0 */
235 240
 	char md5[MD5_LEN];
236 241
 
... ...
@@ -239,7 +244,12 @@ typedef struct cell
239 244
 	short damocles;
240 245
 #endif
241 246
 	/* has the transaction been scheduled to die? */
242
-	enum kill_reason kr;
247
+/*	enum kill_reason kr; */
248
+
249
+	/* to-tags of 200/INVITEs which were received from downstream and 
250
+	 * forwarded or passed to UAC; note that there can be arbitrarily 
251
+	 * many due to downstream forking; */
252
+	struct totag_elem *fwded_totags;
243 253
 }cell_type;
244 254
 
245 255
 
... ...
@@ -266,14 +276,9 @@ struct s_table
266 276
 	struct entry   entrys[ TABLE_ENTRIES ];
267 277
 };
268 278
 
269
-inline static void set_kr( struct cell *t, enum kill_reason kr )
270
-{
271
-	if (t->kr!=0) {
272
-		LOG(L_ERR, "ERROR: set_kr: kill_reason reset: from=%d to=%d\n",
273
-		t->kr, kr);
274
-	}
275
-	t->kr|=kr;
276
-}
279
+
280
+void set_kr( enum kill_reason kr );
281
+enum kill_reason get_kr();
277 282
 
278 283
 struct s_table* get_tm_table();
279 284
 struct s_table* init_hash_table();
... ...
@@ -101,7 +101,7 @@ void tm_shutdown()
101 101
 */
102 102
 int t_release_transaction( struct cell *trans )
103 103
 {
104
-	set_kr(trans,REQ_RLSD);
104
+	set_kr(REQ_RLSD);
105 105
 
106 106
 	reset_timer( & trans->uas.response.fr_timer );
107 107
 	reset_timer( & trans->uas.response.retr_timer );
... ...
@@ -92,10 +92,12 @@ int send_pr_buffer( struct retr_buf *rb,
92 92
 	UNREF_UNSAFE(_T_cell); \
93 93
 	UNLOCK_HASH( (_T_cell)->hash_index ); })
94 94
 #define REF_UNSAFE(_T_cell) ({  (_T_cell)->ref_count++; })
95
+#ifdef _OBSO
95 96
 #define REF(_T_cell) ({ \
96 97
 	LOCK_HASH( (_T_cell)->hash_index ); \
97 98
 	REF_UNSAFE(_T_cell); \
98 99
 	UNLOCK_HASH( (_T_cell)->hash_index ); })
100
+#endif
99 101
 #define INIT_REF_UNSAFE(_T_cell) (_T_cell)->ref_count=1
100 102
 #define IS_REFFED_UNSAFE(_T_cell) ((_T_cell)->ref_count!=0)
101 103
 
... ...
@@ -111,19 +113,14 @@ void tm_shutdown();
111 113
 int  t_add_transaction( struct sip_msg* p_msg  );
112 114
 
113 115
 
114
-/* returns 1 if everything was OK or -1 for error
115
- */
116
+/* returns 1 if everything was OK or -1 for error */
116 117
 int t_release_transaction( struct cell *trans );
117 118
 
118 119
 
119
-/* int forward_serial_branch(struct cell* Trans,int branch); */
120
-int t_put_on_wait(  struct cell  *Trans  );
121 120
 int get_ip_and_port_from_uri( str* uri , unsigned int *param_ip,
122 121
 	unsigned int *param_port);
123 122
 
124 123
 
125
-int t_newtran( struct sip_msg* p_msg );
126
-
127 124
 void put_on_wait(  struct cell  *Trans  );
128 125
 
129 126
 void start_retr( struct retr_buf *rb );
... ...
@@ -75,7 +75,7 @@ char *print_uac_request( struct cell *t, struct sip_msg *i_req,
75 75
 	i_req->new_uri=*uri;
76 76
 
77 77
 	/* ... give apps a chance to change things ... */
78
-	callback_event( TMCB_REQUEST_OUT, t, i_req, -i_req->REQ_METHOD);
78
+	callback_event( TMCB_REQUEST_FWDED, t, i_req, -i_req->REQ_METHOD);
79 79
 
80 80
 	/* ... and build it now */
81 81
 	buf=build_req_buf_from_sip_req( i_req, len, send_sock, i_req->rcv.proto );
... ...
@@ -110,6 +110,45 @@ error01:
110 110
 	return shbuf;
111 111
 }
112 112
 
113
+/* introduce a new uac, which is blind -- it only creates the
114
+   data structures and starts FR timer, but that's it; it does
115
+   not print messages and send anything anywhere; that is good
116
+   for FIFO apps -- the transaction must look operationally
117
+   and FR must be ticking, whereas the request is "forwarded"
118
+   using a non-SIP way and will be replied the same way
119
+*/
120
+int add_blind_uac( /*struct cell *t*/ )
121
+{
122
+	unsigned short branch;
123
+	struct cell *t;
124
+
125
+	t=get_t();
126
+	if (t==T_UNDEFINED || !t ) {
127
+		LOG(L_ERR, "ERROR: add_blind_uac: no transaction context\n");
128
+		return -1;
129
+	}
130
+
131
+	branch=t->nr_of_outgoings;	
132
+	if (branch==MAX_BRANCHES) {
133
+		LOG(L_ERR, "ERROR: add_blind_uac: "
134
+			"maximum number of branches exceeded\n");
135
+		return -1;
136
+	}
137
+	/* make sure it will be replied */
138
+	t->noisy_ctimer=1; 
139
+	t->nr_of_outgoings++;
140
+	/* start FR timer -- protocol set by default to PROTO_NONE,
141
+       which means retransmission timer will not be started
142
+    */
143
+	start_retr(&t->uac[branch].request);
144
+	/* we are on a timer -- don't need to put on wait on script
145
+	   clean-up	
146
+	*/
147
+	set_kr(REQ_FWDED); 
148
+
149
+	return 1; /* success */
150
+}
151
+
113 152
 /* introduce a new uac to transaction; returns its branch id (>=0)
114 153
    or error (<0); it doesn't send a message yet -- a reply to it
115 154
    might interfere with the processes of adding multiple branches
... ...
@@ -343,7 +382,7 @@ int t_forward_nonack( struct cell *t, struct sip_msg* p_msg ,
343 382
 	/* make -Wall happy */
344 383
 	current_uri.s=0;
345 384
 
346
-	set_kr(t, REQ_FWDED);
385
+	set_kr(REQ_FWDED);
347 386
 
348 387
 	if (p_msg->REQ_METHOD==METHOD_CANCEL) {
349 388
 		t_invite=t_lookupOriginalT(  p_msg );
... ...
@@ -40,6 +40,7 @@
40 40
 #include "../../proxy.h"
41 41
 
42 42
 typedef int (*tfwd_f)(struct sip_msg* p_msg , struct proxy_l * proxy );
43
+typedef int (*taddblind_f)( /*struct cell *t */ );
43 44
 
44 45
 int t_replicate(struct sip_msg *p_msg, struct proxy_l * proxy, int proto);
45 46
 char *print_uac_request( struct cell *t, struct sip_msg *i_req,
... ...
@@ -48,6 +49,7 @@ void e2e_cancel( struct sip_msg *cancel_msg, struct cell *t_cancel, struct cell
48 49
 int e2e_cancel_branch( struct sip_msg *cancel_msg, struct cell *t_cancel, struct cell *t_invite, int branch );
49 50
 int add_uac(	struct cell *t, struct sip_msg *request, str *uri,
50 51
 				struct proxy_l *proxy, int proto );
52
+int add_blind_uac( /* struct cell *t */ );
51 53
 int t_forward_nonack( struct cell *t, struct sip_msg* p_msg,
52 54
 						struct proxy_l * p, int proto);
53 55
 int t_forward_ack( struct sip_msg* p_msg );
... ...
@@ -35,83 +35,95 @@
35 35
 struct sip_msg;
36 36
 struct cell;
37 37
 
38
-typedef enum { TMCB_REPLY,  TMCB_E2EACK, TMCB_REPLY_IN, 
39
-	TMCB_REQUEST_OUT, TMCB_LOCAL_COMPLETED, TMCB_ON_NEGATIVE,
40
-	TMCB_END } tmcb_type;
38
+typedef enum { 
39
+		/* input events */
40
+		TMCB_RESPONSE_IN=1, TMCB_REQUEST_IN, TMCB_E2EACK_IN, 
41
+		/* routing decisions in progress */
42
+		TMCB_REQUEST_FWDED, TMCB_RESPONSE_FWDED, TMCB_ON_FAILURE,
43
+		/* completion events */
44
+		TMCB_RESPONSE_OUT, TMCB_LOCAL_COMPLETED, 
45
+		TMCB_END } tmcb_type;
41 46
 
42 47
 /* 
43
-	TMCB_REPLY	-  a reply has been sent out
44
-	  no chance to change anything in the message; 
45
-	  still good enough for many uses, such as accounting
46
-	  of completed transactions; note well that the message
47
-	  passed to the callback may also have value FAKED_REPLY,
48
-	  i.e., refering to it will segfault
49
-	TMCB_REPLY_IN - a reply was received and is about to be forwarded;
50
-	  compared to TMCB_REPLY, it is a very internal callback and
51
-	  you should use it with lot of caution
52
-	  - it allows you to change the message (called before printing
53
-	    the relayed message)
54
-	  - it is called from a reply lock -- it is mroe dangerous and
55
-	    anything you do makes the processes spend more time in
56
-	    the lock, decreasing overall performance
57
-	  - is is called only for replies >100, <300 (final replies
58
-	    might be cached on forking, stored in shmem -- then, there
59
-		is no more easy way to change messages)
60
-	  - as it is called before printing and forwarding, there is
61
-	    no guarantee the message will be sent out -- either can
62
-	    fail
63
-
64
-		Note: none of the reply callbacks will be evoked if
65
-		"silent C timer" hits. Silent C timer is a feature which
66
-		prevents cancellation of a call in progress by a server
67
-		in the middle, when C timer expires. On one side, 
68
-		INVITE transactional state cannot be kept for ever,
69
-		on the other side you want to allow long ringing 
70
-		uninterrupted by a proxy server. The silent_c feature
71
-		-- if circumstances allow -- simply discards transaction
72
-		state when C timer hits, the transaction can then complete
73
-		statelessly. Then, however, the stateful callback will
74
-		NOT be called. If you do not wish this behaviour (e.g.,
75
-		for sake of transaction accounting, in which you do
76
-		not desire users to wait until silent C hits and
77
-		eventually complete an unaccounted transaction), turn
78
-		silent C off either globaly (TM option "noisy_ctimer"
79
-		set to 1) or for a specific transaction (you can for
80
-		example set the transaction member "noisy_timer"
81
-		from request callback.)
82
-
83
-	TMCB_E2EACK - presumably, an end2end ACK was received and
84
-		is about to be processed statelessly; you better don't
85
-	    use this callback as there is no reliable way to match
86
-	    an e2e ACK to an INVITE transaction, we just try it for
87
-	    those, who believe they can't live without knowing about
88
-	    the ACK; There are more reasons why the e2e ACK callback
89
-	    is never triggered: 1) the e2eACK does not pass the server
90
-	    at all 2) the e2e ACK does not match an INVITE transaction
91
-		because its r-uri or via is different
92
-	TMCB_REQUEST_OUT - a request was received and is about to be fwd-ed;
93
-		it is not called on retransmissions; it is called prior to
94
-		printing the relayed message, i.e., changes to it can
95
-		be done
96
-	TMCB_LOCAL_COMPLETED - a local transaction completed; note that
97
-	    the callback parameter may be FAKED_REPLY
98
-	TMCB_MISSED -- transaction was replied with a negative value;
99
-		called from within a REPLY_LOCK, message may be FAKED_REPLY
100
-	TMCB_ON_NEGATIVE -- called whenever a transaction is about to complete
101
-	    with a negative result; it's a great time to introduce a new
102
-	    uac (serial forking) or change the reply code; be cautions
103
-	    though -- it is called from within REPLY_LOCK and careless
104
-	    usage of the callback can easily result in a deadlock; msg
105
-	    is always 0 (callback refers to whole transaction and not
106
-	    to individual message), code is the currently lowest status
107
-	    code
108
-	TMCB_END	- just a bumper
48
+ *  Caution: most of the callbacks work with shmem-ized messages
49
+ *  which you can no more change (e.g., lumps are fixed). Most
50
+ *  reply-processing callbacks are also called from a mutex,
51
+ *  which may cause deadlock if you are not careful. Also, reply
52
+ *  callbacks may pass the value of FAKED_REPLY messages, which
53
+ *  is a non-dereferencable pointer indicating that no message
54
+ *  was received and a timer hit instead.
55
+ *
56
+ *  Callback description:
57
+ *  ---------------------
58
+ *
59
+ * TMCB_REQUEST_IN -- a brand-new request was received and is
60
+ * about to establish transaction; it is not yet cloned and
61
+ * lives in pkg mem -- your last chance to mangle it before
62
+ * it gets shmem-ized (then, it's read-only); it's called from
63
+ * HASH_LOCK, so be careful. It is guaranteed not to be
64
+ * a retransmission.
65
+ *
66
+ * TMCB_RESPONSE_IN -- a brand-new reply was received which matches
67
+ * an existing transaction. It may or may not be a retranmisssion.
68
+ *
69
+ *  TMCB_RESPONSE_OUT -- a final reply was sent out (eiter local 
70
+ *  or proxied) -- there is nothing more you can change from
71
+ *  the callback, it is good for accounting-like uses.
72
+ *
73
+ *    Note: the message passed to callback may also have
74
+ *    value FAKED_REPLY (like other reply callbacks) which
75
+ *    indicates a psedo_reply caused by a timer. Check for
76
+ *    this value before derefing -- you will cause a segfault
77
+ *    otherwise.
78
+ *
79
+ *  TMCB_ON_FAILURE -- called on receipt of a reply or timer;
80
+ *  it means all branches completed with a failure; that's 
81
+ *  a chance for example to add new transaction branches
82
+ *
83
+ *  TMCB_RESPONSE_FWDED -- called when a reply is about to be
84
+ *  forwarded; it is called after a message is received but before
85
+ *  a message is sent out: it is called when the decision is 
86
+ *  made to forward a reply; it is parametrized by pkg message 
87
+ *  which caused the transaction to complete (which is not 
88
+ *  necessarily the same which will be forwarded). As forwarding
89
+ *  has not been executed and may fail, there is no guarentee
90
+ *  a reply will be successfuly sent out at this point of time.
91
+ *
92
+ *     Note: TMCB_REPLY_ON_FAILURE and TMCB_REPLY_FWDED are
93
+ *     called from reply mutex which is used to deterministically
94
+ *     process multiple replies received in parallel. A failure
95
+ *     to set the mutex again or stay too long in the callback
96
+ *     may result in deadlock.
97
+ *
98
+ *     Note: the reply callbacks will not be evoked if "silent
99
+ *     C-timer hits". That's a feature to clean transactional
100
+ *     state from a proxy quickly -- transactions will then
101
+ *     complete statelessly. If you wish to disable this
102
+ *     feature, either set the global option "noisy_ctimer"
103
+ *     to 1, or set t->noisy_ctimer for selected transaction.
104
+ *
105
+ *  TMCB_E2EACK_IN -- called when an ACK belonging to a proxied
106
+ *  INVITE transaction completed with 200 arrived. Note that
107
+ *  because it can be only dialog-wise matched, only the first
108
+ *  transaction occurence will be matched with spirals. If
109
+ *  record-routing is not enabled, you will never receive the
110
+ *  ACK and the callback will be never triggered.
111
+ *
112
+ *
113
+ *  TMCB_REQUEST_FWDED -- request is being forwarded out. It is 
114
+ *  called before a message is forwarded and it is your last
115
+ *  chance to change its shape. 
116
+ *
117
+ *  TMCB_LOCAL COMPLETED -- final reply for localy initiated
118
+ *  transaction arrived. Message may be FAKED_REPLY.
119
+ *
120
+ *  TMCB_END	- just a bumper
109 121
 
110 122
 	see the 'acc' module for an example of callback usage
111 123
 
112 124
 	note that callbacks MUST be installed before forking
113 125
     (callback lists do not live in shmem and have no access
114
-	protection)
126
+	protection), i.e., at best from mod_init functions.
115 127
 */
116 128
 
117 129
 typedef void (transaction_cb) ( struct cell* t, struct sip_msg* msg, 
... ...
@@ -71,6 +71,7 @@
71 71
 #include "../../dprint.h"
72 72
 #include "../../config.h"
73 73
 #include "../../parser/parser_f.h"
74
+#include "../../parser/parse_from.h"
74 75
 #include "../../ut.h"
75 76
 #include "../../timer.h"
76 77
 #include "../../hash_func.h"
... ...
@@ -141,54 +142,178 @@ struct cell *get_t() { return T; }
141 142
 void set_t(struct cell *t) { T=t; }
142 143
 void init_t() {global_msg_id=0; set_t(T_UNDEFINED);}
143 144
 
145
+static inline int parse_dlg( struct sip_msg *msg )
146
+{
147
+	if (parse_headers(msg, HDR_FROM | HDR_CSEQ | HDR_TO, 0)==-1) {
148
+		LOG(L_ERR, "ERROR: tid_matching: From or Cseq or To invalid\n");
149
+		return 0;
150
+	}
151
+	if (parse_from_header(msg)==-1) {
152
+		LOG(L_ERR, "ERROR: tid_matching: From broken\n");
153
+		return 0;
154
+	}
155
+	/* To is automatically parsed through HDR_TO in parse bitmap,
156
+	 * we don't need to worry about it now
157
+	if (parse_to_header(msg)==-1) {
158
+		LOG(L_ERR, "ERROR: tid_matching: To broken\n");
159
+		return 0;
160
+	}
161
+	*/
162
+	return 1;
163
+}
164
+
165
+/* is the ACK (p_msg) in p_msg dialog-wise equal to the INVITE (t_msg) 
166
+ * except to-tags? */
167
+static inline int partial_dlg_matching(struct sip_msg *t_msg, struct sip_msg *p_msg)
168
+{
169
+	struct to_body *inv_from;
170
+
171
+	if (!EQ_LEN(callid)) return 0;
172
+	if (get_cseq(t_msg)->number.len!=get_cseq(p_msg)->number.len)
173
+		return 0;
174
+	inv_from=get_from(t_msg);
175
+	if (!inv_from) {
176
+		LOG(L_ERR, "ERROR: partial_dlg_matching: INV/From not parsed\n");
177
+		return 0;
178
+	}
179
+	if (inv_from->tag_value.len!=get_from(p_msg)->tag_value.len)
180
+		return 0;
181
+	if (!EQ_STR(callid)) 
182
+		return 0;
183
+	if (memcmp(get_cseq(t_msg)->number.s, get_cseq(p_msg)->number.s,
184
+			get_cseq(p_msg)->number.len)!=0)
185
+		return 0;
186
+	if (memcmp(inv_from->tag_value.s, get_from(p_msg)->tag_value.s,
187
+			get_from(p_msg)->tag_value.len)!=0)
188
+		return 0;
189
+	return 1;
190
+}
191
+
192
+/* are to-tags in ACK/200 same as those we sent out? */
193
+static inline int dlg_matching(struct cell *p_cell, struct sip_msg *ack )
194
+{
195
+	if (get_to(ack)->tag_value.len!=p_cell->uas.local_totag.len)
196
+		return 0;
197
+	if (memcmp(get_to(ack)->tag_value.s,p_cell->uas.local_totag.s,
198
+				p_cell->uas.local_totag.len)!=0)
199
+		return 0;
200
+	return 1;
201
+}
202
+
203
+static inline int ack_matching(struct cell *p_cell, struct sip_msg *p_msg) 
204
+{
205
+	/* partial dialog matching -- no to-tag, only from-tag, 
206
+	 * callid, cseq number ; */
207
+	if (!partial_dlg_matching(p_cell->uas.request, p_msg)) 
208
+		return 0;
209
+
210
+  	/* if this transaction is proxied (as opposed to UAS) we're
211
+	 * done now -- we ignore to-tags; the ACK simply belongs to
212
+	 * this UAS part of dialog, whatever to-tag it gained
213
+	 */
214
+	if (p_cell->relaied_reply_branch!=-2) {
215
+		return 2; /* e2e proxied ACK */
216
+	}
217
+	/* it's a local dialog -- we wish to verify to-tags too */
218
+	if (dlg_matching(p_cell, p_msg)) {
219
+		return 1;
220
+	}
221
+	return 0;
222
+}
223
+
224
+/* branch-based transaction matching */
225
+static inline int via_matching( struct via_body *inv_via, 
226
+				struct via_body *ack_via )
227
+{
228
+	if (inv_via->tid.len!=ack_via->tid.len)
229
+		return 0;
230
+	if (memcmp(inv_via->tid.s, ack_via->tid.s,
231
+				ack_via->tid.len)!=0)
232
+		return 0;
233
+	/* ok, tid matches -- now make sure that the
234
+	 * originater matches too to avoid confusion with
235
+	 * different senders generating the same tid
236
+	 */
237
+	if (inv_via->host.len!=ack_via->host.len)
238
+		return 0;;
239
+	if (memcmp(inv_via->host.s, ack_via->host.s,
240
+			ack_via->host.len)!=0)
241
+		return 0;
242
+	if (inv_via->port!=ack_via->port)
243
+		return 0;
244
+	if (inv_via->transport.len!=ack_via->transport.len)
245
+		return 0;
246
+	if (memcmp(inv_via->transport.s, ack_via->transport.s,
247
+			ack_via->transport.len)!=0)
248
+		return 0;
249
+	/* everything matched -- we found it */
250
+	return 1;
251
+}
252
+
144 253
 
145 254
 /* transaction matching a-la RFC-3261 using transaction ID in branch
146
- * (the function assumes there is magic cookie in branch) */
255
+   (the function assumes there is magic cookie in branch) 
256
+   It returns:
257
+	 2 if e2e ACK for a proxied transaction found
258
+     1  if found (covers ACK for local UAS)
259
+	 0  if not found (trans undefined)
260
+*/
147 261
 
148
-static struct cell *tid_matching( int hash_index, 
149
-		struct via_body *via1, 
150
-		enum request_method skip_method)
262
+static int matching_3261( struct sip_msg *p_msg, struct cell **trans,
263
+			enum request_method skip_method)
151 264
 {
152 265
 	struct cell *p_cell;
153 266
 	struct sip_msg  *t_msg;
267
+	struct via_body *via1;
268
+	int is_ack;
269
+	int dlg_parsed;
270
+	int ret;
154 271
 
155
-
272
+	via1=p_msg->via1;
273
+	is_ack=p_msg->REQ_METHOD==METHOD_ACK;
274
+	dlg_parsed=0;
156 275
 	/* update parsed tid */
157 276
 	via1->tid.s=via1->branch->value.s+MCOOKIE_LEN;
158 277
 	via1->tid.len=via1->branch->value.len-MCOOKIE_LEN;
159 278
 
160
-	for ( p_cell = get_tm_table()->entrys[hash_index].first_cell;
279
+	for ( p_cell = get_tm_table()->entrys[p_msg->hash_index].first_cell;
161 280
 		p_cell; p_cell = p_cell->next_cell ) 
162 281
 	{
163 282
 		t_msg=p_cell->uas.request;
164 283
 		if (skip_method & t_msg->REQ_METHOD)
165 284
 			continue;
166
-		if (t_msg->via1->tid.len!=via1->tid.len)
167
-			continue;
168
-		if (memcmp(t_msg->via1->tid.s, via1->tid.s,
169
-				via1->tid.len)!=0)
170
-			continue;
171
-		/* ok, tid matches -- now make sure that the
172
-		 * originater matches too to avoid confusion with
173
-		 * different senders generating the same tid
174
-		 */
175
-		if (via1->host.len!=t_msg->via1->host.len)
176
-			continue;
177
-		if (memcmp(via1->host.s, t_msg->via1->host.s,
178
-					via1->host.len)!=0)
179
-			continue;
180
-		if (via1->port!=t_msg->via1->port)
181
-			continue;
182
-		if (via1->transport.len!=t_msg->via1->transport.len)
285
+
286
+		/* dialog matching needs to be applied for ACK/200s */
287
+		if (is_ack && p_cell->uas.status<300) {
288
+			/* make sure we have parsed all things we need for dialog
289
+			 * matching */
290
+			if (!dlg_parsed) {
291
+				dlg_parsed=1;
292
+				if (!parse_dlg(p_msg)) {
293
+					LOG(L_ERR, "ERROR: tid_matching: dlg parsing failed\n");
294
+					return 0;
295
+				}
296
+			}
297
+			ret=ack_matching(p_cell /* t w/invite */, p_msg /* ack */);
298
+			if (ret>0) {
299
+				*trans=p_cell;
300
+				return ret; /* 2: e2e proxied ACK, 1 e2e UAS ACK */
301
+			}
302
+			/* this ACK is neither local "negative" one, nor a proxied
303
+			 * end-2-end one, nor an end-2-end one for a UAS transaction
304
+			 * -- we failed to match */
183 305
 			continue;
184
-		if (memcmp(via1->transport.s, t_msg->via1->transport.s,
185
-					via1->transport.len)!=0)
306
+		}
307
+		/* now real tid matching occurs  for negative ACKs and any 
308
+	 	 * other requests */
309
+		if (!via_matching(t_msg->via1 /* inv via */, via1 /* ack */ ))
186 310
 			continue;
187 311
 		/* all matched -- we found the transaction ! */
188 312
 		DBG("DEBUG: RFC3261 transaction matched, tid=%.*s\n",
189 313
 			via1->tid.len, via1->tid.s);
190 314
 
191
-		return p_cell;
315
+		*trans=p_cell;
316
+		return 1;
192 317
 	}
193 318
 	/* :-( ... we didn't find any */
194 319
 	DBG("DEBUG: RFC3261 transaction matching failed\n");
... ...
@@ -209,6 +334,7 @@ int t_lookup_request( struct sip_msg* p_msg , int leave_new_locked )
209 334
 	struct sip_msg  *t_msg;
210 335
 	int ret;
211 336
 	struct via_param *branch;
337
+	int match_status;
212 338
 
213 339
 	/* parse all*/
214 340
 	if (check_transaction_quadruple(p_msg)==0)
... ...
@@ -221,8 +347,7 @@ int t_lookup_request( struct sip_msg* p_msg , int leave_new_locked )
221 347
 
222 348
 	/* start searching into the table */
223 349
 	if (!p_msg->hash_index)
224
-		p_msg->hash_index=hash( p_msg->callid->body , 
225
-			get_cseq(p_msg)->number ) ;
350
+		p_msg->hash_index=hash( p_msg->callid->body , get_cseq(p_msg)->number ) ;
226 351
 	isACK = p_msg->REQ_METHOD==METHOD_ACK;
227 352
 	DBG("t_lookup_request: start searching: hash=%d, isACK=%d\n",
228 353
 		p_msg->hash_index,isACK);
... ...
@@ -245,29 +370,20 @@ int t_lookup_request( struct sip_msg* p_msg , int leave_new_locked )
245 370
 			&& memcmp(branch->value.s,MCOOKIE,MCOOKIE_LEN)==0) {
246 371
 		/* huhuhu! the cookie is there -- let's proceed fast */
247 372
 		LOCK_HASH(p_msg->hash_index);
248
-		p_cell=tid_matching(p_msg->hash_index, p_msg->via1, 
249
-				/* skip transactions with different
250
-				 * method; otherwise CANCEL would 
251
-				 * match the previous INVITE trans.
252
-				 */
373
+		match_status=matching_3261(p_msg,&p_cell, 
374
+				/* skip transactions with different method; otherwise CANCEL would 
375
+	 	 		 * match the previous INVITE trans.  */
253 376
 				isACK ? ~METHOD_INVITE: ~p_msg->REQ_METHOD);
254
-		if (p_cell) {
255
-			/* ACK/200 */
256
-			if (isACK && p_cell->uas.status>=200 && p_cell->uas.status<300) {
257
-				/* perhaps there are some spirals on the synonym list, but
258
-				   it makes no sense to iterate the list until bitter end */
259
-				t_ack=p_cell;
260
-				ret=-2;
261
-				goto notfound;
262
-			}
263
-			/* all but 200/ACK */
264
-			goto found;
265
-		} 
266
-		/* new */
267
-		goto notfound;
377
+		switch(match_status) {
378
+				case 0:	goto notfound;	/* no match */
379
+				case 1:	goto found; 	/* match */
380
+				case 2:	goto e2e_ack;	/* e2e proxy ACK */
381
+		}
268 382
 	}
269 383
 
270
-	/* ok -- it's ugly old-fashioned transaction matching */
384
+	/* ok -- it's ugly old-fashioned transaction matching -- it is
385
+	 * a bit simplified to be fast -- we don't do all the comparisons
386
+	 * of parsed uri, which was simply too bloated */
271 387
 	DBG("DEBUG: proceeding to pre-RFC3261 transaction matching\n");
272 388
 
273 389
 	/* lock the whole entry*/
... ...
@@ -303,63 +419,39 @@ int t_lookup_request( struct sip_msg* p_msg , int leave_new_locked )
303 419
 			/* ACK's relate only to INVITEs */
304 420
 			if (t_msg->REQ_METHOD!=METHOD_INVITE) continue;
305 421
 
422
+			/* From|To URI , CallID, CSeq # must be always there */
306 423
 			/* compare lengths now */
307 424
 			if (!EQ_LEN(callid)) continue;
308 425
 			/* CSeq only the number without method ! */
309 426
 			if (get_cseq(t_msg)->number.len!=get_cseq(p_msg)->number.len)
310 427
 				continue;
311 428
 			if (! EQ_LEN(from)) continue;
312
-			/* To only the uri and ... */
429
+			/* To only the uri -- to many UACs screw up tags  */
313 430
 			if (get_to(t_msg)->uri.len!=get_to(p_msg)->uri.len)
314 431
 				continue;
315
-			/* don't care about to-tags -- many UAC screw them
316
-			 * up anyway, and it doesn't hurt if we ignore 
317
-			 * them */
318
-#ifdef ACKTAG
319
-			/* ... its to-tag compared to reply's tag */
320
-			if (p_cell->uas.to_tag.len!=get_to(p_msg)->tag_value.len)
321
-				continue;
322
-#endif
323
-
324
-			/* we first skip r-uri and Via and proceed with
325
-			   content of other header-fields */
326
-
327
-			if ( memcmp(t_msg->callid->body.s, p_msg->callid->body.s,
328
-				p_msg->callid->body.len)!=0) continue;
329
-			if ( memcmp(get_cseq(t_msg)->number.s, get_cseq(p_msg)->number.s,
432
+			if (!EQ_STR(callid)) continue;
433
+			if (memcmp(get_cseq(t_msg)->number.s, get_cseq(p_msg)->number.s,
330 434
 				get_cseq(p_msg)->number.len)!=0) continue;
331 435
 			if (!EQ_STR(from)) continue;
332 436
 			if (memcmp(get_to(t_msg)->uri.s, get_to(p_msg)->uri.s,
333 437
 				get_to(t_msg)->uri.len)!=0) continue;
334
-#ifdef ACKTAG
335
-			if (
336
-#ifdef _BUG
337
-				p_cell->uas.to_tag.len!=0 /* to-tags empty */ || 
338
-#endif
339
-				memcmp(p_cell->uas.to_tag.s, get_to(p_msg)->tag_value.s,
340
-				p_cell->uas.to_tag.len)!=0) continue;
341
-#endif
342
-	
343
-			/* ok, now only r-uri or via can mismatch; they must match
344
-			   for non-2xx; if it is a 2xx, we don't try to match
345
-			   (we might have checked that earlier to speed-up, but
346
-			   we still want to see a diagnosti message telling
347
-			   "this ACK presumably belongs to this 2xx transaction";
348
-			   might change in future); the reason is 2xx ACKs are
349
-			   a separate transaction which may carry different
350
-			   r-uri/via1 and is thus also impossible to match it
351
-			   uniquely to a spiraled transaction;
352
-			*/
353
-			if (p_cell->uas.status>=200 && p_cell->uas.status<300) {
354
-				DBG("DEBUG: an ACK hit a 2xx transaction (T=%p); "
355
-					"considered mismatch\n", p_cell );
356
-				/* perhaps there are some spirals on the synonym list, but
357
-				   it makes no sense to iterate the list until bitter end */
358
-				t_ack=p_cell;
359
-				ret=-2;
360
-				break;
438
+
439
+			/* it is e2e ACK/200 */
440
+			if (p_cell->uas.status<300) {
441
+				/* all criteria for proxied ACK are ok */
442
+				if (p_cell->relaied_reply_branch!=-2) 
443
+					goto e2e_ack;
444
+				/* it's a local UAS transaction */
445
+				if (dlg_matching(p_cell, p_msg))
446
+					goto found;
447
+				continue;
361 448
 			}
362
-			/* its for a >= 300 ... everything must match ! */
449
+
450
+			/* it is not an e2e ACK/200 -- perhaps it is 
451
+			 * local negative case; in which case we will want
452
+			 * more elements to match: r-uri and via; allow
453
+			 * mismatching r-uri as an config option for broken
454
+			 * UACs */
363 455
 			if (ruri_matching && ! EQ_REQ_URI_LEN ) continue;
364 456
 			if (! EQ_VIA_LEN(via1)) continue;
365 457
 			if (ruri_matching && !EQ_REQ_URI_STR) continue;
... ...
@@ -378,12 +470,21 @@ notfound:
378 470
 		UNLOCK_HASH(p_msg->hash_index);
379 471
 	}
380 472
 	DBG("DEBUG: t_lookup_request: no transaction found\n");
381
-	return ret;
473
+	return -1;
474
+
475
+e2e_ack:
476
+	t_ack=p_cell;	/* e2e proxied ACK */
477
+	set_t(0);
478
+	if (!leave_new_locked) {
479
+		UNLOCK_HASH(p_msg->hash_index);
480
+	}
481
+	DBG("DEBUG: t_lookup_request: e2e proxy ACK found\n");
482
+	return -2;
382 483
 
383 484
 found:
384 485
 	set_t(p_cell);
385 486
 	REF_UNSAFE( T );
386
-	set_kr(T, REQ_EXIST);
487
+	set_kr(REQ_EXIST);
387 488
 	UNLOCK_HASH( p_msg->hash_index );
388 489
 	DBG("DEBUG: t_lookup_request: transaction found (T=%p)\n",T);
389 490
 	return 1;
... ...
@@ -402,6 +503,7 @@ struct cell* t_lookupOriginalT(  struct sip_msg* p_msg )
402 503
 	unsigned int     hash_index;
403 504
 	struct sip_msg  *t_msg;
404 505
 	struct via_param *branch;
506
+	int ret;
405 507
 
406 508
 
407 509
 	/* start searching in the table */
... ...
@@ -423,12 +525,12 @@ struct cell* t_lookupOriginalT(  struct sip_msg* p_msg )
423 525
 			&& memcmp(branch->value.s,MCOOKIE,MCOOKIE_LEN)==0) {
424 526
 		/* huhuhu! the cookie is there -- let's proceed fast */
425 527
 		LOCK_HASH(hash_index);
426
-		p_cell=tid_matching(hash_index, p_msg->via1, 
528
+		ret=matching_3261(p_msg, &p_cell,
427 529
 				/* we are seeking the original transaction --
428 530
 				 * skip CANCEL transactions during search
429 531
 				 */
430 532
 				METHOD_CANCEL);
431
-		if (p_cell) goto found; else goto notfound;
533
+		if (ret==1) goto found; else goto notfound;
432 534
 	}
433 535
 
434 536
 	/* no cookies --proceed to old-fashioned pre-3261 t-matching */
... ...
@@ -658,6 +760,23 @@ int t_reply_matching( struct sip_msg *p_msg , int *p_branch )
658 760
 		REF_UNSAFE( T );
659 761
 		UNLOCK_HASH(hash_index);
660 762
 		DBG("DEBUG: t_reply_matching: reply matched (T=%p)!\n",T);
763
+		/* if this is a 200 for INVITE, we will wish to store to-tags to be
764
+		 * able to distuingish retransmissions later and not to call
765
+ 		 * TMCB_RESPONSE_OUT uselessly; we do it only if callbacks are
766
+		 * enabled -- except callback customers, nobody cares about 
767
+		 * retransmissions of multiple 200/INV or ACK/200s
768
+		 */
769
+		if (p_cell->is_invite && p_msg->REPLY_STATUS>=200 
770
+				&& p_msg->REPLY_STATUS<300 
771
+				&& ( (!p_cell->local && 
772
+					(callback_array[TMCB_RESPONSE_OUT]||
773
+						callback_array[TMCB_E2EACK_IN]))
774
+					|| (p_cell->local && callback_array[TMCB_LOCAL_COMPLETED]) )) {
775
+			if (parse_headers(p_msg, HDR_TO, 0)==-1) {
776
+				LOG(L_ERR, "ERROR: t_reply_matching: to parsing failed\n");
777
+			}
778
+		}
779
+		callback_event(TMCB_RESPONSE_IN, T, p_msg, p_msg->REPLY_STATUS);
661 780
 		return 1;
662 781
 	} /* for cycle */
663 782
 
... ...
@@ -675,10 +794,12 @@ nomatch2:
675 794
 
676 795
 
677 796
 
678
-/* Functions update T (T gets either a valid pointer in it or it equals zero) if no transaction
679
-  * for current message exists;
680
-  * it returns 1 if found, 0 if not found, -1 on error
681
-  */
797
+/* Determine current transaction
798
+ *
799
+ *                   Found      Not Found     Error (e.g. parsing)
800
+ *  Return Value     1          0             -1
801
+ *  T                ptr        0             T_UNDEFINED
802
+ */
682 803
 int t_check( struct sip_msg* p_msg , int *param_branch )
683 804
 {
684 805
 	int local_branch;
... ...
@@ -693,8 +814,20 @@ int t_check( struct sip_msg* p_msg , int *param_branch )
693 814
 		/* transaction lookup */
694 815
 		if ( p_msg->first_line.type==SIP_REQUEST ) {
695 816
 			/* force parsing all the needed headers*/
696
-			if (parse_headers(p_msg, HDR_EOH, 0 )==-1)
817
+			if (parse_headers(p_msg, HDR_EOH, 0 )==-1) {
818
+				LOG(L_ERR, "ERROR: t_check: parsing error\n");
697 819
 				return -1;
820
+			}
821
+			/* in case, we act as UAS for INVITE and reply with 200,
822
+			 * we will need to run dialog-matching for subsequent
823
+			 * ACK, for which we need From-tag; We also need from-tag
824
+			 * in case people want to have proxied e2e ACKs accounted
825
+			 */
826
+			if (p_msg->REQ_METHOD==METHOD_INVITE 
827
+							&& parse_from_header(p_msg)==-1) {
828
+				LOG(L_ERR, "ERROR: t_check: from parsing failed\n");
829
+				return -1;
830
+			}
698 831
 			t_lookup_request( p_msg , 0 /* unlock before returning */ );
699 832
 		} else {
700 833
 			/* we need Via for branch and Cseq method to distinguish
... ...
@@ -738,7 +871,7 @@ int t_check( struct sip_msg* p_msg , int *param_branch )
738 871
 			DBG("DEBUG: t_check: T previously sought and not found\n");
739 872
 	}
740 873
 
741
-	return ((T)?1:0) ;
874
+	return T ? (T==T_UNDEFINED ? -1 : 1 ) : 0;
742 875
 }
743 876
 
744 877
 int init_rb( struct retr_buf *rb, struct sip_msg *msg)
... ...
@@ -840,6 +973,21 @@ int t_newtran( struct sip_msg* p_msg )
840 973
 	if (lret<0) {
841 974
 		new_cell=0;
842 975
 		if ( p_msg->REQ_METHOD!=METHOD_ACK ) {
976
+			/* REVIEW */
977
+			/* for ACK-dlw-wise matching, we want From-tags */
978
+			if (p_msg->REQ_METHOD==METHOD_INVITE) {
979
+				if (parse_from_header(p_msg)<0) {
980
+					LOG(L_ERR, "ERROR: t_newtran: no valid From\n");
981
+					return E_BAD_REQ;
982
+				}
983
+			}
984
+			/* REVIEW */
985
+			/* make sure uri will be parsed before cloning */
986
+			if (parse_sip_msg_uri(p_msg)<0) {
987
+				LOG(L_ERR, "ERROR: t_new_tran: uri invalid\n");
988
+				return E_BAD_REQ;
989
+			}
990
+			
843 991
 			/* add new transaction */
844 992
 			new_cell = build_cell( p_msg ) ;
845 993
 			if  ( !new_cell ){
... ...
@@ -867,6 +1015,7 @@ int t_newtran( struct sip_msg* p_msg )
867 1015
 
868 1016
 				new_cell->method=new_cell->uas.request->first_line.u.request.method;
869 1017
 				new_cell->is_invite=p_msg->REQ_METHOD==METHOD_INVITE;
1018
+
870 1019
 			}
871 1020
 
872 1021
 		}
... ...
@@ -875,7 +1024,9 @@ int t_newtran( struct sip_msg* p_msg )
875 1024
 		if (lret==-2) {
876 1025
 				REF_UNSAFE(t_ack);
877 1026
 				UNLOCK_HASH(p_msg->hash_index);
878
-				callback_event( TMCB_E2EACK, t_ack, p_msg, p_msg->REQ_METHOD );
1027
+				if (unmatched_totag(t_ack, p_msg)) {
1028
+						callback_event( TMCB_E2EACK_IN, t_ack, p_msg, p_msg->REQ_METHOD );
1029
+				}
879 1030
 				UNREF(t_ack);
880 1031
 		} else { /* not e2e ACK */
881 1032
 			UNLOCK_HASH(p_msg->hash_index);
... ...
@@ -915,10 +1066,13 @@ int t_newtran( struct sip_msg* p_msg )
915 1066
 
916 1067
 int t_unref( struct sip_msg* p_msg  )
917 1068
 {
1069
+	enum kill_reason kr;
1070
+
918 1071
 	if (T==T_UNDEFINED || T==T_NULL_CELL)
919 1072
 		return -1;
920
-	if (T->kr==0 
921
-		||(p_msg->REQ_METHOD==METHOD_ACK && !(T->kr & REQ_RLSD))) {
1073
+	kr=get_kr();
1074
+	if (kr==0 
1075
+		||(p_msg->REQ_METHOD==METHOD_ACK && !(kr & REQ_RLSD))) {
922 1076
 		LOG(L_WARN, "WARNING: script writer didn't release transaction\n");
923 1077
 		t_release_transaction(T);
924 1078
 	}
... ...
@@ -927,7 +1081,6 @@ int t_unref( struct sip_msg* p_msg  )
927 1081
 	return 1;
928 1082
 }
929 1083
 
930
-#ifdef VOICE_MAIL
931 1084
 int t_get_trans_ident(struct sip_msg* p_msg, unsigned int* hash_index, unsigned int* label)
932 1085
 {
933 1086
     struct cell* t;
... ...
@@ -947,14 +1100,13 @@ int t_get_trans_ident(struct sip_msg* p_msg, unsigned int* hash_index, unsigned
947 1100
     return 1;
948 1101
 }
949 1102
 
950
-int t_lookup_ident(struct sip_msg** p_msg, unsigned int hash_index, unsigned int label)
1103
+int t_lookup_ident(struct cell ** trans, unsigned int hash_index, unsigned int label)
951 1104
 {
952
-    int ret = 0;
953 1105
     struct cell* p_cell;
954 1106
 
955 1107
     if(hash_index >= TABLE_ENTRIES){
956
-	LOG(L_ERR,"ERROR: t_lookup_ident: invalid hash_index=%u\n",hash_index);
957
-	return -1;
1108
+		LOG(L_ERR,"ERROR: t_lookup_ident: invalid hash_index=%u\n",hash_index);
1109
+		return -1;
958 1110
     }
959 1111
 
960 1112
     LOCK_HASH(hash_index);
... ...
@@ -963,21 +1115,23 @@ int t_lookup_ident(struct sip_msg** p_msg, unsigned int hash_index, unsigned int
963 1115
     for ( p_cell = get_tm_table()->entrys[hash_index].first_cell;
964 1116
 	  p_cell; p_cell = p_cell->next_cell ) 
965 1117
     {
966
-	if(p_cell->label == label){
967
-	    ret = 1;
968
-	    break;
969
-	}
1118
+		if(p_cell->label == label){
1119
+			REF_UNSAFE(p_cell);
1120
+    		UNLOCK_HASH(hash_index);
1121
+			set_t(p_cell);
1122
+			*trans=p_cell;
1123
+			DBG("DEBUG: t_lookup_ident: transaction found\n");
1124
+			return 1;
1125
+		}
970 1126
     }
1127
+	
1128
+	UNLOCK_HASH(hash_index);
1129
+	set_t(0);
1130
+	*trans=p_cell;
971 1131
 
972
-    if(ret==1){
973
-	DBG("DEBUG: t_lookup_ident: transaction found\n");
974
-	*p_msg = p_cell->uas.request;
975
-    }
976
-    else
977 1132
 	DBG("DEBUG: t_lookup_ident: transaction not found\n");
978 1133
     
979
-    UNLOCK_HASH(hash_index);
980
-    return ret;
1134
+    return -1;
981 1135
 }
982 1136
 
983 1137
 int t_is_local(struct sip_msg* p_msg)
... ...
@@ -995,8 +1149,3 @@ int t_is_local(struct sip_msg* p_msg)
995 1149
     
996 1150
     return t->local;
997 1151
 }
998
-
999
-#endif
1000
-
1001
-
1002
-
... ...
@@ -75,7 +75,6 @@ struct cell *get_t();
75 75
  * primarily set by lookup functions */
76 76
 void set_t(struct cell *t);
77 77
 
78
-#ifdef VOICE_MAIL
79 78
 
80 79
 #define T_GET_TI       "t_get_trans_ident"
81 80
 #define T_LOOKUP_IDENT "t_lookup_ident"
... ...
@@ -83,12 +82,11 @@ void set_t(struct cell *t);
83 82
 
84 83
 typedef int (*tislocal_f)(struct sip_msg*);
85 84
 typedef int (*tget_ti_f)(struct sip_msg*, unsigned int*, unsigned int*);
86
-typedef int (*tlookup_ident_f)(struct sip_msg**, unsigned int, unsigned int);
85
+typedef int (*tlookup_ident_f)(struct cell**, unsigned int, unsigned int);
87 86
 
88 87
 int t_is_local(struct sip_msg*);
89 88
 int t_get_trans_ident(struct sip_msg* p_msg, unsigned int* hash_index, unsigned int* label);
90
-int t_lookup_ident(struct sip_msg** p_msg, unsigned int hash_index, unsigned int label);
91
-#endif
89
+int t_lookup_ident(struct cell** trans, unsigned int hash_index, unsigned int label);
92 90
 
93 91
 #endif
94 92
 
... ...
@@ -36,12 +36,15 @@
36 36
  * 2003-01-19  faked lump list created in on_reply handlers
37 37
  */
38 38
 
39
+
40
+#include <assert.h>
39 41
 #include "defs.h"
40 42
 
41 43
 #include "../../comp_defs.h"
42 44
 
43 45
 #include "../../hash_func.h"
44 46
 #include "t_funcs.h"
47
+#include "h_table.h"
45 48
 #include "../../dprint.h"
46 49
 #include "../../config.h"
47 50
 #include "../../parser/parser_f.h"
... ...
@@ -73,6 +76,7 @@ static char *tm_tag_suffix;
73 76
 /* where to go if there is no positive reply */
74 77
 static int goto_on_negative=0;
75 78
 
79
+
76 80
 /* we store the reply_route # in private memory which is
77 81
    then processed during t_relay; we cannot set this value
78 82
    before t_relay creates transaction context or after
... ...
@@ -101,6 +105,88 @@ void tm_init_tags()
101 105
 		"SER-TM/tags", TM_TAG_SEPARATOR );
102 106
 }
103 107
 
108
+/* returns 0 if the message was previously acknowledged
109
+ * (i.e., no E2EACK callback is needed) and one if the
110
+ * callback shall be executed */
111
+int unmatched_totag(struct cell *t, struct sip_msg *ack)
112
+{
113
+	struct totag_elem *i;
114
+	str *tag;
115
+
116
+	if (parse_headers(ack, HDR_TO,0)==-1 || 
117
+				!ack->to ) {
118
+		LOG(L_ERR, "ERROR: ack_totag_set: To invalid\n");
119
+		return 1;
120
+	}
121
+	tag=&get_to(ack)->tag_value;
122
+	for (i=t->fwded_totags; i; i=i->next) {
123
+		if (i->tag.len==tag->len
124
+				&& memcmp(i->tag.s, tag->s, tag->len)==0) {
125
+			DBG("DEBUG: totag for e2e ACK found: %d\n", i->acked);
126
+			/* to-tag recorded, and an ACK has been received for it */
127
+			if (i->acked) return 0;
128
+			/* to-tag recorded, but this ACK came for the first time */
129
+			i->acked=1;
130
+			return 1;
131
+		}
132
+	}
133
+	/* surprising: to-tag never sighted before */
134
+	return 1;
135
+}
136
+
137
+
138
+/* append a newly received tag from a 200/INVITE to 
139
+ * transaction's set; (only safe if called from within
140
+ * a REPLY_LOCK); it returns 1 if such a to tag already
141
+ * exists
142
+ */
143
+inline static int update_totag_set(struct cell *t, struct sip_msg *ok)
144
+{
145
+	struct totag_elem *i, *n;
146
+	str *tag;
147
+	char *s;
148
+
149
+	if (!ok->to || !ok->to->parsed) {
150
+		LOG(L_ERR, "ERROR: update_totag_set: to not parsed\n");
151
+		return 0;
152
+	}
153
+	tag=&get_to(ok)->tag_value;
154
+	if (!tag->s) {
155
+		LOG(L_ERR, "ERROR: update_totag_set: no tag in to\n");
156
+		return 0;
157
+	}
158
+
159
+	for (i=t->fwded_totags; i; i=i->next) {
160
+		if (i->tag.len==tag->len
161
+				&& memcmp(i->tag.s, tag->s, tag->len) ==0 )
162
+			/* to tag already recorded */
163
+#ifdef XL_DEBUG
164
+			LOG(L_CRIT, "DEBUG: update_totag_set: totag retranmission\n");
165
+#else
166
+			DBG("DEBUG: update_totag_set: totag retranmission\n");
167
+#endif
168
+			return 1;
169
+	}
170
+	/* that's a new to-tag -- record it */
171
+	shm_lock();
172
+	n=(struct totag_elem*) shm_malloc_unsafe(sizeof(struct totag_elem));
173
+	s=(char *)shm_malloc_unsafe(tag->len);
174
+	shm_unlock();
175
+	if (!s || !n) {
176
+		LOG(L_ERR, "ERROR: update_totag_set: no  memory \n");
177
+		if (n) shm_free(n);
178
+		if (s) shm_free(s);
179
+		return 0;
180
+	}
181
+	memset(n, 0, sizeof(struct totag_elem));
182
+	memcpy(s, tag->s, tag->len );
183
+	n->tag.s=s;n->tag.len=tag->len;
184
+	n->next=t->fwded_totags;
185
+	t->fwded_totags=n;
186
+	DBG("DEBUG: update_totag_set: new totag \n");
187
+	return 0;
188
+}
189
+
104 190
 
105 191
 static char *build_ack(struct sip_msg* rpl,struct cell *trans,int branch,
106 192
 	unsigned int *ret_len)
... ...
@@ -315,7 +401,7 @@ static enum rps t_should_relay_response( struct cell *Trans , int new_code,
315 401
 		/* no more pending branches -- try if that changes after
316 402
 		   a callback
317 403
 		*/
318
-		callback_event( TMCB_ON_NEGATIVE, Trans, 
404
+		callback_event( TMCB_ON_FAILURE, Trans, 
319 405
 			lowest_b==branch?reply:Trans->uac[lowest_b].reply, 
320 406
 			lowest_s );
321 407
 
... ...
@@ -458,18 +544,7 @@ error:
458 544
 }
459 545
 
460 546
 
461
-#ifdef VOICE_MAIL
462
-static int _reply_light( struct cell *trans, char* buf, unsigned int len,
463
-			 unsigned int code, char * text, 
464
-			 char *to_tag, unsigned int to_tag_len, int lock );
465 547
 
466
-int t_reply_light( struct cell *t, char* buf, unsigned int len,
467
-		   unsigned int code, char * text,
468
-		   char *to_tag, unsigned int to_tag_len )
469
-{
470
-    return _reply_light( t, buf, len, code, text, to_tag, to_tag_len, 1 /* lock replies */ );
471
-}
472
-#endif
473 548
 
474 549
 int t_reply( struct cell *t, struct sip_msg* p_msg, unsigned int code, 
475 550
 	char * text )
... ...
@@ -484,69 +559,26 @@ int t_reply_unsafe( struct cell *t, struct sip_msg* p_msg, unsigned int code,
484 559
 }
485 560
 
486 561
 
487
-
488
-/* send a UAS reply
489
- * returns 1 if everything was OK or -1 for error
490
- */
491
-static int _reply( struct cell *trans, struct sip_msg* p_msg, 
492
-	unsigned int code, char * text, int lock )
562
+static inline void update_local_tags(struct cell *trans, 
563
+				struct bookmark *bm, char *dst_buffer,
564
+				char *src_buffer /* to which bm refers */)
493 565
 {
494
-#ifndef VOICE_MAIL
495
-	unsigned int len, buf_len=0;
496
-	char * buf;
497
-	struct retr_buf *rb;
498
-
499
-	branch_bm_t cancel_bitmap;
500
-#else
501
-	unsigned int len;
502
-	char * buf;
503
-#endif
504
-
505
-	if (code>=200) set_kr(trans,REQ_RPLD);
506
-	/*
507
-	buf = build_res_buf_from_sip_req(code,text,trans->uas.tag->s,
508
-		trans->uas.tag->len, trans->uas.request,&len);
509
-	*/
510
-#ifndef VOICE_MAIL
511
-	cancel_bitmap=0;
512
-#endif
513
-	/* compute the buffer in private memory prior to entering lock;
514
-	 * create to-tag if needed */
515
-	if (code>=180 && p_msg->to 
516
-			&& (get_to(p_msg)->tag_value.s==0 
517
-			    || get_to(p_msg)->tag_value.len==0)) {
518
-		calc_crc_suffix( p_msg, tm_tag_suffix );
519
-		buf = build_res_buf_from_sip_req(code,text, 
520
-				tm_tags, TOTAG_VALUE_LEN, 
521
-				p_msg,&len);
522
-#ifdef VOICE_MAIL
523
-
524
-		return _reply_light(trans,buf,len,code,text,
525
-				    tm_tags, TOTAG_VALUE_LEN,
526
-				    lock);
527
-#endif
528
-	} else {
529
-		buf = build_res_buf_from_sip_req(code,text, 0,0, /* no to-tag */
530
-			p_msg,&len);
531
-#ifdef VOICE_MAIL
532
-
533
-		return _reply_light(trans,buf,len,code,text,
534
-				    0,0, /* no to-tag */
535
-				    lock);
536
-#endif
566
+	if (bm->to_tag_val.s) {
567
+		trans->uas.local_totag.s=bm->to_tag_val.s-src_buffer+dst_buffer;
568
+		trans->uas.local_totag.len=bm->to_tag_val.len;
537 569
 	}
538
-	DBG("DEBUG: t_reply: buffer computed\n");
539
-#ifdef VOICE_MAIL
540 570
 }
541 571
 
572
+
542 573
 static int _reply_light( struct cell *trans, char* buf, unsigned int len,
543 574
 			 unsigned int code, char * text, 
544
-			 char *to_tag, unsigned int to_tag_len, int lock )
575
+			 char *to_tag, unsigned int to_tag_len, int lock,
576
+			 struct bookmark *bm	)
545 577
 {
546 578
 	struct retr_buf *rb;
547
-	unsigned int buf_len=0;
548
-	branch_bm_t cancel_bitmap=0;
549
-#endif
579
+	unsigned int buf_len;
580
+	branch_bm_t cancel_bitmap;
581
+
550 582
 	if (!buf)
551 583
 	{
552 584
 		DBG("DEBUG: t_reply: response building failed\n");
... ...
@@ -560,6 +592,7 @@ static int _reply_light( struct cell *trans, char* buf, unsigned int len,
560 592
 		goto error;
561 593
 	}
562 594
 
595
+	cancel_bitmap=0;
563 596
 	if (lock) LOCK_REPLIES( trans );
564 597
 	if (trans->is_invite) which_cancel(trans, &cancel_bitmap );
565 598
 	if (trans->uas.status>=200) {
... ...
@@ -567,6 +600,19 @@ static int _reply_light( struct cell *trans, char* buf, unsigned int len,
567 600
 			" when a final %d was sent out\n", code, trans->uas.status);
568 601
 		goto error2;
569 602
 	}
603
+
604
+#ifdef _TOTAG
605
+	if(to_tag){
606
+	    trans->uas.to_tag.s = (char*)shm_resize( trans->uas.to_tag.s, to_tag_len );
607
+	    if(! trans->uas.to_tag.s ){
608
+			LOG(L_ERR, "ERROR: t_reply: cannot allocate shmem buffer\n");
609
+			goto error2; 
610
+	    }
611
+	    trans->uas.to_tag.len = to_tag_len;
612
+	    memcpy( trans->uas.to_tag.s, to_tag, to_tag_len );
613
+	}
614
+#endif
615
+
570 616
 	rb = & trans->uas.response;
571 617
 	rb->activ_type=code;
572 618
 
... ...
@@ -576,27 +622,17 @@ static int _reply_light( struct cell *trans, char* buf, unsigned int len,
576 622
 	/* puts the reply's buffer to uas.response */
577 623
 	if (! rb->buffer ) {
578 624
 			LOG(L_ERR, "ERROR: t_reply: cannot allocate shmem buffer\n");
579
-			goto error2;
625
+			goto error3;
580 626
 	}
627
+	update_local_tags(trans, bm, rb->buffer, buf);
628
+
581 629
 	rb->buffer_len = len ;
582 630
 	memcpy( rb->buffer , buf , len );
583
-#ifdef VOICE_MAIL
584
-	if(to_tag){
585
-	    trans->uas.to_tag.s = (char*)shm_resize( trans->uas.to_tag.s, to_tag_len );
586
-	    if(! trans->uas.to_tag.s ){
587
-			LOG(L_ERR, "ERROR: t_reply: cannot allocate shmem buffer\n");
588
-			// Is it ok? or should i free rb->buffer also, 
589
-			// or will it be freed in free_cell() ?
590
-			goto error2; 
591
-	    }
592
-	    trans->uas.to_tag.len = to_tag_len;
593
-	    memcpy( trans->uas.to_tag.s, to_tag, to_tag_len );
594
-	}
595
-#endif
596 631
 	/* needs to be protected too because what timers are set depends
597 632
 	   on current transactions status */
598 633
 	/* t_update_timers_after_sending_reply( rb ); */
599 634
 	update_reply_stats( code );
635
+	trans->relaied_reply_branch=-2;
600 636
 	tm_stats->replied_localy++;
601 637
 	if (lock) UNLOCK_REPLIES( trans );
602 638
 	
... ...
@@ -609,7 +645,7 @@ static int _reply_light( struct cell *trans, char* buf, unsigned int len,
609 645
 			if (trans->completion_cb) 
610 646
 				trans->completion_cb( trans, FAKED_REPLY, code, 0 /* empty param */);
611 647
 		} else {
612
-			callback_event( TMCB_REPLY, trans, FAKED_REPLY, code );
648
+			callback_event( TMCB_RESPONSE_OUT, trans, FAKED_REPLY, code );
613 649
 		}
614 650
 
615 651
 		cleanup_uac_timers( trans );
... ...
@@ -632,6 +668,13 @@ static int _reply_light( struct cell *trans, char* buf, unsigned int len,
632 668
 	DBG("DEBUG: t_reply: finished\n");
633 669
 	return 1;
634 670
 
671
+error3:
672
+#ifdef _TOTAG
673
+	if (totag) {
674
+		shm_free(trans->uas.to_tag.s);
675
+		trans->uas.to_tag.s=0;
676
+	}
677
+#endif
635 678
 error2:
636 679
 	if (lock) UNLOCK_REPLIES( trans );
637 680
 	pkg_free ( buf );
... ...
@@ -644,11 +687,47 @@ error:
644 687
 	return -1;
645 688
 }
646 689
 
690
+/* send a UAS reply
691
+ * returns 1 if everything was OK or -1 for error
692
+ */
693
+static int _reply( struct cell *trans, struct sip_msg* p_msg, 
694
+	unsigned int code, char * text, int lock )
695
+{
696
+	unsigned int len;
697
+	char * buf;
698
+	struct bookmark bm;
699
+
700
+	if (code>=200) set_kr(REQ_RPLD);
701
+	/* compute the buffer in private memory prio