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 197
 	 #-DNO_LOG
198 198
 
199 199
 #PROFILE=  -pg #set this if you want profiling
200
-#mode = debug
200
+mode = debug
201 201
 ifeq ($(mode),)
202 202
 	mode = release
203 203
 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 84
 	char *b;
85 85
 	int i;
86 86
 	struct sip_msg *rpl;
87
+	struct totag_elem *tt, *foo;
87 88
 
88 89
 	release_cell_lock( dead_cell );
89 90
 	shm_lock();
... ...
@@ -116,6 +131,15 @@ void free_cell( struct cell* dead_cell )
116 116
 		}
117 117
 	}
118 118
 
119
+	/* collected to tags */
120
+	tt=dead_cell->fwded_totags;
121
+	while(tt) {
122
+		foo=tt->next;
123
+		shm_free_unsafe(tt->tag.s);
124
+		shm_free_unsafe(tt);
125
+		tt=foo;
126
+	}
127
+
119 128
 	/* the cell's body */
120 129
 	shm_free_unsafe( dead_cell );
121 130
 
... ...
@@ -158,6 +182,9 @@ struct cell*  build_cell( struct sip_msg* p_msg )
158 158
 	/*fprintf(stderr,"before clone VIA |%.*s|\n",via_len(p_msg->via1),
159 159
 		via_s(p_msg->via1,p_msg));*/
160 160
 
161
+	callback_event(TMCB_REQUEST_IN, new_cell, p_msg, 
162
+			p_msg ? p_msg->REQ_METHOD : METHOD_UNDEF );
163
+
161 164
 	if (p_msg) {
162 165
 		new_cell->uas.request = sip_msg_cloner(p_msg);
163 166
 		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 151
 }ua_client_type;
152 152
 
153 153
 
154
+struct totag_elem {
155
+	str tag;
156
+	short acked;
157
+	struct totag_elem *next;
158
+};
154 159
 
155 160
 /* transaction context */
156 161
 
... ...
@@ -205,7 +216,8 @@ typedef struct cell
205 205
 
206 206
 	/* number of forks */
207 207
 	int nr_of_outgoings;
208
-	/* nr of replied branch */
208
+	/* nr of replied branch; 0..MAX_BRANCHES=branch value,
209
+	 * -1 no reply, -2 local reply */
209 210
 	int relaied_reply_branch;
210 211
 	/* UA Server */
211 212
 	struct ua_server  uas;
... ...
@@ -221,16 +233,9 @@ typedef struct cell
221 221
 	   dropping when C timer hits
222 222
 	*/
223 223
 	int noisy_ctimer;
224
-	/* is it a local transaction ? */
224
+	/* is it a local UAC transaction ? */
225 225
 	int local;
226 226
 
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 227
 	/* MD5checksum  (meaningful only if syn_branch=0 */
235 228
 	char md5[MD5_LEN];
236 229
 
... ...
@@ -239,7 +244,12 @@ typedef struct cell
239 239
 	short damocles;
240 240
 #endif
241 241
 	/* has the transaction been scheduled to die? */
242
-	enum kill_reason kr;
242
+/*	enum kill_reason kr; */
243
+
244
+	/* to-tags of 200/INVITEs which were received from downstream and 
245
+	 * forwarded or passed to UAC; note that there can be arbitrarily 
246
+	 * many due to downstream forking; */
247
+	struct totag_elem *fwded_totags;
243 248
 }cell_type;
244 249
 
245 250
 
... ...
@@ -266,14 +276,9 @@ struct s_table
266 266
 	struct entry   entrys[ TABLE_ENTRIES ];
267 267
 };
268 268
 
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
-}
269
+
270
+void set_kr( enum kill_reason kr );
271
+enum kill_reason get_kr();
277 272
 
278 273
 struct s_table* get_tm_table();
279 274
 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 111
 int  t_add_transaction( struct sip_msg* p_msg  );
112 112
 
113 113
 
114
-/* returns 1 if everything was OK or -1 for error
115
- */
114
+/* returns 1 if everything was OK or -1 for error */
116 115
 int t_release_transaction( struct cell *trans );
117 116
 
118 117
 
119
-/* int forward_serial_branch(struct cell* Trans,int branch); */
120
-int t_put_on_wait(  struct cell  *Trans  );
121 118
 int get_ip_and_port_from_uri( str* uri , unsigned int *param_ip,
122 119
 	unsigned int *param_port);
123 120
 
124 121
 
125
-int t_newtran( struct sip_msg* p_msg );
126
-
127 122
 void put_on_wait(  struct cell  *Trans  );
128 123
 
129 124
 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 343
 	/* make -Wall happy */
344 344
 	current_uri.s=0;
345 345
 
346
-	set_kr(t, REQ_FWDED);
346
+	set_kr(REQ_FWDED);
347 347
 
348 348
 	if (p_msg->REQ_METHOD==METHOD_CANCEL) {
349 349
 		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 48
 int e2e_cancel_branch( struct sip_msg *cancel_msg, struct cell *t_cancel, struct cell *t_invite, int branch );
49 49
 int add_uac(	struct cell *t, struct sip_msg *request, str *uri,
50 50
 				struct proxy_l *proxy, int proto );
51
+int add_blind_uac( /* struct cell *t */ );
51 52
 int t_forward_nonack( struct cell *t, struct sip_msg* p_msg,
52 53
 						struct proxy_l * p, int proto);
53 54
 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 141
 void set_t(struct cell *t) { T=t; }
142 142
 void init_t() {global_msg_id=0; set_t(T_UNDEFINED);}
143 143
 
144
+static inline int parse_dlg( struct sip_msg *msg )
145
+{
146
+	if (parse_headers(msg, HDR_FROM | HDR_CSEQ | HDR_TO, 0)==-1) {
147
+		LOG(L_ERR, "ERROR: tid_matching: From or Cseq or To invalid\n");
148
+		return 0;
149
+	}
150
+	if (parse_from_header(msg)==-1) {
151
+		LOG(L_ERR, "ERROR: tid_matching: From broken\n");
152
+		return 0;
153
+	}
154
+	/* To is automatically parsed through HDR_TO in parse bitmap,
155
+	 * we don't need to worry about it now
156
+	if (parse_to_header(msg)==-1) {
157
+		LOG(L_ERR, "ERROR: tid_matching: To broken\n");
158
+		return 0;
159
+	}
160
+	*/
161
+	return 1;
162
+}
163
+
164
+/* is the ACK (p_msg) in p_msg dialog-wise equal to the INVITE (t_msg) 
165
+ * except to-tags? */
166
+static inline int partial_dlg_matching(struct sip_msg *t_msg, struct sip_msg *p_msg)
167
+{
168
+	struct to_body *inv_from;
169
+
170
+	if (!EQ_LEN(callid)) return 0;
171
+	if (get_cseq(t_msg)->number.len!=get_cseq(p_msg)->number.len)
172
+		return 0;
173
+	inv_from=get_from(t_msg);
174
+	if (!inv_from) {
175
+		LOG(L_ERR, "ERROR: partial_dlg_matching: INV/From not parsed\n");
176
+		return 0;
177
+	}
178
+	if (inv_from->tag_value.len!=get_from(p_msg)->tag_value.len)
179
+		return 0;
180
+	if (!EQ_STR(callid)) 
181
+		return 0;
182
+	if (memcmp(get_cseq(t_msg)->number.s, get_cseq(p_msg)->number.s,
183
+			get_cseq(p_msg)->number.len)!=0)
184
+		return 0;
185
+	if (memcmp(inv_from->tag_value.s, get_from(p_msg)->tag_value.s,
186
+			get_from(p_msg)->tag_value.len)!=0)
187
+		return 0;
188
+	return 1;
189
+}
190
+
191
+/* are to-tags in ACK/200 same as those we sent out? */
192
+static inline int dlg_matching(struct cell *p_cell, struct sip_msg *ack )
193
+{
194
+	if (get_to(ack)->tag_value.len!=p_cell->uas.local_totag.len)
195
+		return 0;
196
+	if (memcmp(get_to(ack)->tag_value.s,p_cell->uas.local_totag.s,
197
+				p_cell->uas.local_totag.len)!=0)
198
+		return 0;
199
+	return 1;
200
+}
201
+
202
+static inline int ack_matching(struct cell *p_cell, struct sip_msg *p_msg) 
203
+{
204
+	/* partial dialog matching -- no to-tag, only from-tag, 
205
+	 * callid, cseq number ; */
206
+	if (!partial_dlg_matching(p_cell->uas.request, p_msg)) 
207
+		return 0;
208
+
209
+  	/* if this transaction is proxied (as opposed to UAS) we're
210
+	 * done now -- we ignore to-tags; the ACK simply belongs to
211
+	 * this UAS part of dialog, whatever to-tag it gained
212
+	 */
213
+	if (p_cell->relaied_reply_branch!=-2) {
214
+		return 2; /* e2e proxied ACK */
215
+	}
216
+	/* it's a local dialog -- we wish to verify to-tags too */
217
+	if (dlg_matching(p_cell, p_msg)) {
218
+		return 1;
219
+	}
220
+	return 0;
221
+}
222
+
223
+/* branch-based transaction matching */
224
+static inline int via_matching( struct via_body *inv_via, 
225
+				struct via_body *ack_via )
226
+{
227
+	if (inv_via->tid.len!=ack_via->tid.len)
228
+		return 0;
229
+	if (memcmp(inv_via->tid.s, ack_via->tid.s,
230
+				ack_via->tid.len)!=0)
231
+		return 0;
232
+	/* ok, tid matches -- now make sure that the
233
+	 * originater matches too to avoid confusion with
234
+	 * different senders generating the same tid
235
+	 */
236
+	if (inv_via->host.len!=ack_via->host.len)
237
+		return 0;;
238
+	if (memcmp(inv_via->host.s, ack_via->host.s,
239
+			ack_via->host.len)!=0)
240
+		return 0;
241
+	if (inv_via->port!=ack_via->port)
242
+		return 0;
243
+	if (inv_via->transport.len!=ack_via->transport.len)
244
+		return 0;
245
+	if (memcmp(inv_via->transport.s, ack_via->transport.s,
246
+			ack_via->transport.len)!=0)
247
+		return 0;
248
+	/* everything matched -- we found it */
249
+	return 1;
250
+}
251
+
144 252
 
145 253
 /* transaction matching a-la RFC-3261 using transaction ID in branch
146
- * (the function assumes there is magic cookie in branch) */
254
+   (the function assumes there is magic cookie in branch) 
255
+   It returns:
256
+	 2 if e2e ACK for a proxied transaction found
257
+     1  if found (covers ACK for local UAS)
258
+	 0  if not found (trans undefined)
259
+*/
147 260
 
148
-static struct cell *tid_matching( int hash_index, 
149
-		struct via_body *via1, 
150
-		enum request_method skip_method)
261
+static int matching_3261( struct sip_msg *p_msg, struct cell **trans,
262
+			enum request_method skip_method)
151 263
 {
152 264
 	struct cell *p_cell;
153 265
 	struct sip_msg  *t_msg;
266
+	struct via_body *via1;
267
+	int is_ack;
268
+	int dlg_parsed;
269
+	int ret;
154 270
 
155
-
271
+	via1=p_msg->via1;
272
+	is_ack=p_msg->REQ_METHOD==METHOD_ACK;
273
+	dlg_parsed=0;
156 274
 	/* update parsed tid */
157 275
 	via1->tid.s=via1->branch->value.s+MCOOKIE_LEN;
158 276
 	via1->tid.len=via1->branch->value.len-MCOOKIE_LEN;
159 277
 
160
-	for ( p_cell = get_tm_table()->entrys[hash_index].first_cell;
278
+	for ( p_cell = get_tm_table()->entrys[p_msg->hash_index].first_cell;
161 279
 		p_cell; p_cell = p_cell->next_cell ) 
162 280
 	{
163 281
 		t_msg=p_cell->uas.request;
164 282
 		if (skip_method & t_msg->REQ_METHOD)
165 283
 			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)
284
+
285
+		/* dialog matching needs to be applied for ACK/200s */
286
+		if (is_ack && p_cell->uas.status<300) {
287
+			/* make sure we have parsed all things we need for dialog
288
+			 * matching */
289
+			if (!dlg_parsed) {
290
+				dlg_parsed=1;
291
+				if (!parse_dlg(p_msg)) {
292
+					LOG(L_ERR, "ERROR: tid_matching: dlg parsing failed\n");
293
+					return 0;
294
+				}
295
+			}
296
+			ret=ack_matching(p_cell /* t w/invite */, p_msg /* ack */);
297
+			if (ret>0) {
298
+				*trans=p_cell;
299
+				return ret; /* 2: e2e proxied ACK, 1 e2e UAS ACK */
300
+			}
301
+			/* this ACK is neither local "negative" one, nor a proxied
302
+			 * end-2-end one, nor an end-2-end one for a UAS transaction
303
+			 * -- we failed to match */
183 304
 			continue;
184
-		if (memcmp(via1->transport.s, t_msg->via1->transport.s,
185
-					via1->transport.len)!=0)
305
+		}
306
+		/* now real tid matching occurs  for negative ACKs and any 
307
+	 	 * other requests */
308
+		if (!via_matching(t_msg->via1 /* inv via */, via1 /* ack */ ))
186 309
 			continue;
187 310
 		/* all matched -- we found the transaction ! */
188 311
 		DBG("DEBUG: RFC3261 transaction matched, tid=%.*s\n",
189 312
 			via1->tid.len, via1->tid.s);
190 313
 
191
-		return p_cell;
314
+		*trans=p_cell;
315
+		return 1;
192 316
 	}
193 317
 	/* :-( ... we didn't find any */
194 318
 	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 209
 	struct sip_msg  *t_msg;
210 210
 	int ret;
211 211
 	struct via_param *branch;
212
+	int match_status;
212 213
 
213 214
 	/* parse all*/
214 215
 	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 221
 
222 222
 	/* start searching into the table */
223 223
 	if (!p_msg->hash_index)
224
-		p_msg->hash_index=hash( p_msg->callid->body , 
225
-			get_cseq(p_msg)->number ) ;
224
+		p_msg->hash_index=hash( p_msg->callid->body , get_cseq(p_msg)->number ) ;
226 225
 	isACK = p_msg->REQ_METHOD==METHOD_ACK;
227 226
 	DBG("t_lookup_request: start searching: hash=%d, isACK=%d\n",
228 227
 		p_msg->hash_index,isACK);
... ...
@@ -245,29 +370,20 @@ int t_lookup_request( struct sip_msg* p_msg , int leave_new_locked )
245 245
 			&& memcmp(branch->value.s,MCOOKIE,MCOOKIE_LEN)==0) {
246 246
 		/* huhuhu! the cookie is there -- let's proceed fast */
247 247
 		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
-				 */
248
+		match_status=matching_3261(p_msg,&p_cell, 
249
+				/* skip transactions with different method; otherwise CANCEL would 
250
+	 	 		 * match the previous INVITE trans.  */
253 251
 				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;
252
+		switch(match_status) {
253
+				case 0:	goto notfound;	/* no match */
254
+				case 1:	goto found; 	/* match */
255
+				case 2:	goto e2e_ack;	/* e2e proxy ACK */
256
+		}
268 257
 	}
269 258
 
270
-	/* ok -- it's ugly old-fashioned transaction matching */
259
+	/* ok -- it's ugly old-fashioned transaction matching -- it is
260
+	 * a bit simplified to be fast -- we don't do all the comparisons
261
+	 * of parsed uri, which was simply too bloated */
271 262
 	DBG("DEBUG: proceeding to pre-RFC3261 transaction matching\n");
272 263
 
273 264
 	/* lock the whole entry*/
... ...
@@ -303,63 +419,39 @@ int t_lookup_request( struct sip_msg* p_msg , int leave_new_locked )
303 303
 			/* ACK's relate only to INVITEs */
304 304
 			if (t_msg->REQ_METHOD!=METHOD_INVITE) continue;
305 305
 
306
+			/* From|To URI , CallID, CSeq # must be always there */
306 307
 			/* compare lengths now */
307 308
 			if (!EQ_LEN(callid)) continue;
308 309
 			/* CSeq only the number without method ! */
309 310
 			if (get_cseq(t_msg)->number.len!=get_cseq(p_msg)->number.len)
310 311
 				continue;
311 312
 			if (! EQ_LEN(from)) continue;
312
-			/* To only the uri and ... */
313
+			/* To only the uri -- to many UACs screw up tags  */
313 314
 			if (get_to(t_msg)->uri.len!=get_to(p_msg)->uri.len)
314 315
 				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,
316
+			if (!EQ_STR(callid)) continue;
317
+			if (memcmp(get_cseq(t_msg)->number.s, get_cseq(p_msg)->number.s,
330 318
 				get_cseq(p_msg)->number.len)!=0) continue;
331 319
 			if (!EQ_STR(from)) continue;
332 320
 			if (memcmp(get_to(t_msg)->uri.s, get_to(p_msg)->uri.s,
333 321
 				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;
322
+
323
+			/* it is e2e ACK/200 */
324
+			if (p_cell->uas.status<300) {
325
+				/* all criteria for proxied ACK are ok */
326
+				if (p_cell->relaied_reply_branch!=-2) 
327
+					goto e2e_ack;
328
+				/* it's a local UAS transaction */
329
+				if (dlg_matching(p_cell, p_msg))
330
+					goto found;
331
+				continue;
361 332
 			}
362
-			/* its for a >= 300 ... everything must match ! */
333
+
334
+			/* it is not an e2e ACK/200 -- perhaps it is 
335
+			 * local negative case; in which case we will want
336
+			 * more elements to match: r-uri and via; allow
337
+			 * mismatching r-uri as an config option for broken
338
+			 * UACs */
363 339
 			if (ruri_matching && ! EQ_REQ_URI_LEN ) continue;
364 340
 			if (! EQ_VIA_LEN(via1)) continue;
365 341
 			if (ruri_matching && !EQ_REQ_URI_STR) continue;
... ...
@@ -378,12 +470,21 @@ notfound:
378 378
 		UNLOCK_HASH(p_msg->hash_index);
379 379
 	}
380 380
 	DBG("DEBUG: t_lookup_request: no transaction found\n");
381
-	return ret;
381
+	return -1;
382
+
383
+e2e_ack:
384
+	t_ack=p_cell;	/* e2e proxied ACK */
385
+	set_t(0);
386
+	if (!leave_new_locked) {
387
+		UNLOCK_HASH(p_msg->hash_index);
388
+	}
389
+	DBG("DEBUG: t_lookup_request: e2e proxy ACK found\n");
390
+	return -2;
382 391
 
383 392
 found:
384 393
 	set_t(p_cell);
385 394
 	REF_UNSAFE( T );
386
-	set_kr(T, REQ_EXIST);
395
+	set_kr(REQ_EXIST);
387 396
 	UNLOCK_HASH( p_msg->hash_index );
388 397
 	DBG("DEBUG: t_lookup_request: transaction found (T=%p)\n",T);
389 398
 	return 1;
... ...
@@ -402,6 +503,7 @@ struct cell* t_lookupOriginalT(  struct sip_msg* p_msg )
402 402
 	unsigned int     hash_index;
403 403
 	struct sip_msg  *t_msg;
404 404
 	struct via_param *branch;
405
+	int ret;
405 406
 
406 407
 
407 408
 	/* start searching in the table */
... ...
@@ -423,12 +525,12 @@ struct cell* t_lookupOriginalT(  struct sip_msg* p_msg )
423 423
 			&& memcmp(branch->value.s,MCOOKIE,MCOOKIE_LEN)==0) {
424 424
 		/* huhuhu! the cookie is there -- let's proceed fast */
425 425
 		LOCK_HASH(hash_index);
426
-		p_cell=tid_matching(hash_index, p_msg->via1, 
426
+		ret=matching_3261(p_msg, &p_cell,
427 427
 				/* we are seeking the original transaction --
428 428
 				 * skip CANCEL transactions during search
429 429
 				 */
430 430
 				METHOD_CANCEL);
431
-		if (p_cell) goto found; else goto notfound;
431
+		if (ret==1) goto found; else goto notfound;
432 432
 	}
433 433
 
434 434
 	/* 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 658
 		REF_UNSAFE( T );
659 659
 		UNLOCK_HASH(hash_index);
660 660
 		DBG("DEBUG: t_reply_matching: reply matched (T=%p)!\n",T);
661
+		/* if this is a 200 for INVITE, we will wish to store to-tags to be
662
+		 * able to distuingish retransmissions later and not to call
663
+ 		 * TMCB_RESPONSE_OUT uselessly; we do it only if callbacks are
664
+		 * enabled -- except callback customers, nobody cares about 
665
+		 * retransmissions of multiple 200/INV or ACK/200s
666
+		 */
667
+		if (p_cell->is_invite && p_msg->REPLY_STATUS>=200 
668
+				&& p_msg->REPLY_STATUS<300 
669
+				&& ( (!p_cell->local && 
670
+					(callback_array[TMCB_RESPONSE_OUT]||
671
+						callback_array[TMCB_E2EACK_IN]))
672
+					|| (p_cell->local && callback_array[TMCB_LOCAL_COMPLETED]) )) {
673
+			if (parse_headers(p_msg, HDR_TO, 0)==-1) {
674
+				LOG(L_ERR, "ERROR: t_reply_matching: to parsing failed\n");
675
+			}
676
+		}
677
+		callback_event(TMCB_RESPONSE_IN, T, p_msg, p_msg->REPLY_STATUS);
661 678
 		return 1;
662 679
 	} /* for cycle */
663 680
 
... ...
@@ -675,10 +794,12 @@ nomatch2:
675 675
 
676 676
 
677 677
 
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
-  */
678
+/* Determine current transaction
679
+ *
680
+ *                   Found      Not Found     Error (e.g. parsing)
681
+ *  Return Value     1          0             -1
682
+ *  T                ptr        0             T_UNDEFINED
683
+ */
682 684
 int t_check( struct sip_msg* p_msg , int *param_branch )
683 685
 {
684 686
 	int local_branch;
... ...
@@ -693,8 +814,20 @@ int t_check( struct sip_msg* p_msg , int *param_branch )
693 693
 		/* transaction lookup */
694 694
 		if ( p_msg->first_line.type==SIP_REQUEST ) {
695 695
 			/* force parsing all the needed headers*/
696
-			if (parse_headers(p_msg, HDR_EOH, 0 )==-1)
696
+			if (parse_headers(p_msg, HDR_EOH, 0 )==-1) {
697
+				LOG(L_ERR, "ERROR: t_check: parsing error\n");
697 698
 				return -1;
699
+			}
700
+			/* in case, we act as UAS for INVITE and reply with 200,
701
+			 * we will need to run dialog-matching for subsequent
702
+			 * ACK, for which we need From-tag; We also need from-tag
703
+			 * in case people want to have proxied e2e ACKs accounted
704
+			 */
705
+			if (p_msg->REQ_METHOD==METHOD_INVITE 
706
+							&& parse_from_header(p_msg)==-1) {
707
+				LOG(L_ERR, "ERROR: t_check: from parsing failed\n");
708
+				return -1;
709
+			}
698 710
 			t_lookup_request( p_msg , 0 /* unlock before returning */ );
699 711
 		} else {
700 712
 			/* 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 738
 			DBG("DEBUG: t_check: T previously sought and not found\n");
739 739
 	}
740 740
 
741
-	return ((T)?1:0) ;
741
+	return T ? (T==T_UNDEFINED ? -1 : 1 ) : 0;
742 742
 }
743 743
 
744 744
 int init_rb( struct retr_buf *rb, struct sip_msg *msg)
... ...
@@ -840,6 +973,21 @@ int t_newtran( struct sip_msg* p_msg )
840 840
 	if (lret<0) {
841 841
 		new_cell=0;
842 842
 		if ( p_msg->REQ_METHOD!=METHOD_ACK ) {
843
+			/* REVIEW */
844
+			/* for ACK-dlw-wise matching, we want From-tags */
845
+			if (p_msg->REQ_METHOD==METHOD_INVITE) {
846
+				if (parse_from_header(p_msg)<0) {
847
+					LOG(L_ERR, "ERROR: t_newtran: no valid From\n");
848
+					return E_BAD_REQ;
849
+				}
850
+			}
851
+			/* REVIEW */
852
+			/* make sure uri will be parsed before cloning */
853
+			if (parse_sip_msg_uri(p_msg)<0) {
854
+				LOG(L_ERR, "ERROR: t_new_tran: uri invalid\n");
855
+				return E_BAD_REQ;
856
+			}
857
+			
843 858
 			/* add new transaction */
844 859
 			new_cell = build_cell( p_msg ) ;
845 860
 			if  ( !new_cell ){
... ...
@@ -867,6 +1015,7 @@ int t_newtran( struct sip_msg* p_msg )
867 867
 
868 868
 				new_cell->method=new_cell->uas.request->first_line.u.request.method;
869 869
 				new_cell->is_invite=p_msg->REQ_METHOD==METHOD_INVITE;
870
+
870 871
 			}
871 872
 
872 873
 		}
... ...
@@ -875,7 +1024,9 @@ int t_newtran( struct sip_msg* p_msg )
875 875
 		if (lret==-2) {
876 876
 				REF_UNSAFE(t_ack);
877 877
 				UNLOCK_HASH(p_msg->hash_index);
878
-				callback_event( TMCB_E2EACK, t_ack, p_msg, p_msg->REQ_METHOD );
878
+				if (unmatched_totag(t_ack, p_msg)) {
879
+						callback_event( TMCB_E2EACK_IN, t_ack, p_msg, p_msg->REQ_METHOD );
880
+				}
879 881
 				UNREF(t_ack);
880 882
 		} else { /* not e2e ACK */
881 883
 			UNLOCK_HASH(p_msg->hash_index);
... ...
@@ -915,10 +1066,13 @@ int t_newtran( struct sip_msg* p_msg )
915 915
 
916 916
 int t_unref( struct sip_msg* p_msg  )
917 917
 {
918
+	enum kill_reason kr;
919
+
918 920
 	if (T==T_UNDEFINED || T==T_NULL_CELL)
919 921
 		return -1;
920
-	if (T->kr==0 
921
-		||(p_msg->REQ_METHOD==METHOD_ACK && !(T->kr & REQ_RLSD))) {
922
+	kr=get_kr();
923
+	if (kr==0 
924
+		||(p_msg->REQ_METHOD==METHOD_ACK && !(kr & REQ_RLSD))) {
922 925
 		LOG(L_WARN, "WARNING: script writer didn't release transaction\n");
923 926
 		t_release_transaction(T);
924 927
 	}
... ...
@@ -927,7 +1081,6 @@ int t_unref( struct sip_msg* p_msg  )
927 927
 	return 1;
928 928
 }
929 929
 
930
-#ifdef VOICE_MAIL
931 930
 int t_get_trans_ident(struct sip_msg* p_msg, unsigned int* hash_index, unsigned int* label)
932 931
 {
933 932
     struct cell* t;
... ...
@@ -947,14 +1100,13 @@ int t_get_trans_ident(struct sip_msg* p_msg, unsigned int* hash_index, unsigned
947 947
     return 1;
948 948
 }
949 949
 
950
-int t_lookup_ident(struct sip_msg** p_msg, unsigned int hash_index, unsigned int label)
950
+int t_lookup_ident(struct cell ** trans, unsigned int hash_index, unsigned int label)
951 951
 {
952
-    int ret = 0;
953 952
     struct cell* p_cell;
954 953
 
955 954
     if(hash_index >= TABLE_ENTRIES){
956
-	LOG(L_ERR,"ERROR: t_lookup_ident: invalid hash_index=%u\n",hash_index);
957
-	return -1;
955
+		LOG(L_ERR,"ERROR: t_lookup_ident: invalid hash_index=%u\n",hash_index);
956
+		return -1;
958 957
     }
959 958
 
960 959
     LOCK_HASH(hash_index);
... ...
@@ -963,21 +1115,23 @@ int t_lookup_ident(struct sip_msg** p_msg, unsigned int hash_index, unsigned int
963 963
     for ( p_cell = get_tm_table()->entrys[hash_index].first_cell;
964 964
 	  p_cell; p_cell = p_cell->next_cell ) 
965 965
     {
966
-	if(p_cell->label == label){
967
-	    ret = 1;
968
-	    break;
969
-	}
966
+		if(p_cell->label == label){
967
+			REF_UNSAFE(p_cell);
968
+    		UNLOCK_HASH(hash_index);
969
+			set_t(p_cell);
970
+			*trans=p_cell;
971
+			DBG("DEBUG: t_lookup_ident: transaction found\n");
972
+			return 1;
973
+		}
970 974
     }
975
+	
976
+	UNLOCK_HASH(hash_index);
977
+	set_t(0);
978
+	*trans=p_cell;
971 979
 
972
-    if(ret==1){
973
-	DBG("DEBUG: t_lookup_ident: transaction found\n");
974
-	*p_msg = p_cell->uas.request;
975
-    }
976
-    else
977 980
 	DBG("DEBUG: t_lookup_ident: transaction not found\n");
978 981
     
979
-    UNLOCK_HASH(hash_index);
980
-    return ret;
982
+    return -1;
981 983
 }
982 984
 
983 985
 int t_is_local(struct sip_msg* p_msg)
... ...
@@ -995,8 +1149,3 @@ int t_is_local(struct sip_msg* p_msg)
995 995
     
996 996
     return t->local;
997 997
 }
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 83
 
84 84
 typedef int (*tislocal_f)(struct sip_msg*);
85 85
 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);
86
+typedef int (*tlookup_ident_f)(struct cell**, unsigned int, unsigned int);
87 87
 
88 88
 int t_is_local(struct sip_msg*);
89 89
 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
90
+int t_lookup_ident(struct cell** trans, unsigned int hash_index, unsigned int label);
92 91
 
93 92
 #endif
94 93
 
... ...
@@ -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 73
 /* where to go if there is no positive reply */
74 74
 static int goto_on_negative=0;
75 75
 
76
+
76 77
 /* we store the reply_route # in private memory which is
77 78
    then processed during t_relay; we cannot set this value
78 79
    before t_relay creates transaction context or after
... ...
@@ -101,6 +105,88 @@ void tm_init_tags()
101 101
 		"SER-TM/tags", TM_TAG_SEPARATOR );
102 102
 }
103 103
 
104
+/* returns 0 if the message was previously acknowledged
105
+ * (i.e., no E2EACK callback is needed) and one if the
106
+ * callback shall be executed */
107
+int unmatched_totag(struct cell *t, struct sip_msg *ack)
108
+{
109
+	struct totag_elem *i;
110
+	str *tag;
111
+
112
+	if (parse_headers(ack, HDR_TO,0)==-1 || 
113
+				!ack->to ) {
114
+		LOG(L_ERR, "ERROR: ack_totag_set: To invalid\n");
115
+		return 1;
116
+	}
117
+	tag=&get_to(ack)->tag_value;
118
+	for (i=t->fwded_totags; i; i=i->next) {
119
+		if (i->tag.len==tag->len
120
+				&& memcmp(i->tag.s, tag->s, tag->len)==0) {
121
+			DBG("DEBUG: totag for e2e ACK found: %d\n", i->acked);
122
+			/* to-tag recorded, and an ACK has been received for it */
123
+			if (i->acked) return 0;
124
+			/* to-tag recorded, but this ACK came for the first time */
125
+			i->acked=1;
126
+			return 1;
127
+		}
128
+	}
129
+	/* surprising: to-tag never sighted before */
130
+	return 1;
131
+}
132
+
133
+
134
+/* append a newly received tag from a 200/INVITE to 
135
+ * transaction's set; (only safe if called from within
136
+ * a REPLY_LOCK); it returns 1 if such a to tag already
137
+ * exists
138
+ */
139
+inline static int update_totag_set(struct cell *t, struct sip_msg *ok)
140
+{
141
+	struct totag_elem *i, *n;
142
+	str *tag;
143
+	char *s;
144
+
145
+	if (!ok->to || !ok->to->parsed) {
146
+		LOG(L_ERR, "ERROR: update_totag_set: to not parsed\n");
147
+		return 0;
148
+	}
149
+	tag=&get_to(ok)->tag_value;
150
+	if (!tag->s) {
151
+		LOG(L_ERR, "ERROR: update_totag_set: no tag in to\n");
152
+		return 0;
153
+	}
154
+
155
+	for (i=t->fwded_totags; i; i=i->next) {
156
+		if (i->tag.len==tag->len
157
+				&& memcmp(i->tag.s, tag->s, tag->len) ==0 )
158
+			/* to tag already recorded */
159
+#ifdef XL_DEBUG
160
+			LOG(L_CRIT, "DEBUG: update_totag_set: totag retranmission\n");
161
+#else
162
+			DBG("DEBUG: update_totag_set: totag retranmission\n");
163
+#endif
164
+			return 1;
165
+	}
166
+	/* that's a new to-tag -- record it */
167
+	shm_lock();
168
+	n=(struct totag_elem*) shm_malloc_unsafe(sizeof(struct totag_elem));
169
+	s=(char *)shm_malloc_unsafe(tag->len);
170
+	shm_unlock();
171
+	if (!s || !n) {
172
+		LOG(L_ERR, "ERROR: update_totag_set: no  memory \n");
173
+		if (n) shm_free(n);
174
+		if (s) shm_free(s);
175
+		return 0;
176
+	}
177
+	memset(n, 0, sizeof(struct totag_elem));
178
+	memcpy(s, tag->s, tag->len );
179
+	n->tag.s=s;n->tag.len=tag->len;
180
+	n->next=t->fwded_totags;
181
+	t->fwded_totags=n;
182
+	DBG("DEBUG: update_totag_set: new totag \n");
183
+	return 0;
184
+}
185
+
104 186
 
105 187
 static char *build_ack(struct sip_msg* rpl,struct cell *trans,int branch,
106 188
 	unsigned int *ret_len)
... ...
@@ -315,7 +401,7 @@ static enum rps t_should_relay_response( struct cell *Trans , int new_code,
315 315
 		/* no more pending branches -- try if that changes after
316 316
 		   a callback
317 317
 		*/
318
-		callback_event( TMCB_ON_NEGATIVE, Trans, 
318
+		callback_event( TMCB_ON_FAILURE, Trans, 
319 319
 			lowest_b==branch?reply:Trans->uac[lowest_b].reply, 
320 320
 			lowest_s );
321 321
 
... ...
@@ -458,18 +544,7 @@ error:
458 458
 }
459 459
 
460 460
 
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 461
 
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 462
 
474 463
 int t_reply( struct cell *t, struct sip_msg* p_msg, unsigned int code, 
475 464
 	char * text )
... ...
@@ -484,69 +559,26 @@ int t_reply_unsafe( struct cell *t, struct sip_msg* p_msg, unsigned int code,
484 484
 }
485 485
 
486 486
 
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 )
487
+static inline void update_local_tags(struct cell *trans, 
488
+				struct bookmark *bm, char *dst_buffer,
489
+				char *src_buffer /* to which bm refers */)
493 490
 {
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
491
+	if (bm->to_tag_val.s) {
492
+		trans->uas.local_totag.s=bm->to_tag_val.s-src_buffer+dst_buffer;
493
+		trans->uas.local_totag.len=bm->to_tag_val.len;
537 494
 	}
538
-	DBG("DEBUG: t_reply: buffer computed\n");
539
-#ifdef VOICE_MAIL
540 495
 }
541 496
 
497
+
542 498
 static int _reply_light( struct cell *trans, char* buf, unsigned int len,
543 499
 			 unsigned int code, char * text, 
544
-			 char *to_tag, unsigned int to_tag_len, int lock )
500
+			 char *to_tag, unsigned int to_tag_len, int lock,
501
+			 struct bookmark *bm	)
545 502
 {
546 503
 	struct retr_buf *rb;
547
-	unsigned int buf_len=0;
548
-	branch_bm_t cancel_bitmap=0;
549
-#endif
504
+	unsigned int buf_len;
505
+	branch_bm_t cancel_bitmap;
506
+
550 507
 	if (!buf)
551 508
 	{
552 509
 		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 560
 		goto error;
561 561
 	}
562 562
 
563
+	cancel_bitmap=0;
563 564
 	if (lock) LOCK_REPLIES( trans );
564 565
 	if (trans->is_invite) which_cancel(trans, &cancel_bitmap );
565 566
 	if (trans->uas.status>=200) {
... ...
@@ -567,6 +600,19 @@ static int _reply_light( struct cell *trans, char* buf, unsigned int len,
567 567
 			" when a final %d was sent out\n", code, trans->uas.status);
568 568
 		goto error2;
569 569
 	}
570
+
571
+#ifdef _TOTAG
572
+	if(to_tag){
573
+	    trans->uas.to_tag.s = (char*)shm_resize( trans->uas.to_tag.s, to_tag_len );
574
+	    if(! trans->uas.to_tag.s ){
575
+			LOG(L_ERR, "ERROR: t_reply: cannot allocate shmem buffer\n");
576
+			goto error2; 
577
+	    }
578
+	    trans->uas.to_tag.len = to_tag_len;
579
+	    memcpy( trans->uas.to_tag.s, to_tag, to_tag_len );
580
+	}
581
+#endif
582
+
570 583
 	rb = & trans->uas.response;
571 584
 	rb->activ_type=code;
572 585
 
... ...
@@ -576,27 +622,17 @@ static int _reply_light( struct cell *trans, char* buf, unsigned int len,
576 576
 	/* puts the reply's buffer to uas.response */
577 577
 	if (! rb->buffer ) {
578 578
 			LOG(L_ERR, "ERROR: t_reply: cannot allocate shmem buffer\n");
579
-			goto error2;
579
+			goto error3;
580 580
 	}
581
+	update_local_tags(trans, bm, rb->buffer, buf);
582
+
581 583
 	rb->buffer_len = len ;
582 584
 	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 585
 	/* needs to be protected too because what timers are set depends
597 586
 	   on current transactions status */
598 587
 	/* t_update_timers_after_sending_reply( rb ); */
599 588
 	update_reply_stats( code );
589
+	trans->relaied_reply_branch=-2;
600 590
 	tm_stats->replied_localy++;
601 591
 	if (lock) UNLOCK_REPLIES( trans );
602 592
 	
... ...
@@ -609,7 +645,7 @@ static int _reply_light( struct cell *trans, char* buf, unsigned int len,
609 609
 			if (trans->completion_cb) 
610 610
 				trans->completion_cb( trans, FAKED_REPLY, code, 0 /* empty param */);
611 611
 		} else {
612
-			callback_event( TMCB_REPLY, trans, FAKED_REPLY, code );
612
+			callback_event( TMCB_RESPONSE_OUT, trans, FAKED_REPLY, code );
613 613
 		}
614 614
 
615 615
 		cleanup_uac_timers( trans );
... ...
@@ -632,6 +668,13 @@ static int _reply_light( struct cell *trans, char* buf, unsigned int len,
632 632
 	DBG("DEBUG: t_reply: finished\n");
633 633
 	return 1;
634 634
 
635
+error3:
636
+#ifdef _TOTAG
637
+	if (totag) {
638
+		shm_free(trans->uas.to_tag.s);
639
+		trans->uas.to_tag.s=0;
640
+	}
641
+#endif
635 642
 error2:
636 643
 	if (lock) UNLOCK_REPLIES( trans );
637 644
 	pkg_free ( buf );
... ...
@@ -644,11 +687,47 @@ error:
644 644
 	return -1;
645 645
 }
646 646
 
647
+/* send a UAS reply
648
+ * returns 1 if everything was OK or -1 for error
649
+ */
650
+static int _reply( struct cell *trans, struct sip_msg* p_msg, 
651
+	unsigned int code, char * text, int lock )
652
+{
653
+	unsigned int len;
654
+	char * buf;
655
+	struct bookmark bm;
656
+
657
+	if (code>=200) set_kr(REQ_RPLD);
658
+	/* compute the buffer in private memory prior to entering lock;
659