Browse code

- request matching using tid (RFC3216) introduced

Jiri Kuthan authored on 21/10/2002 15:46:27
Showing 7 changed files
... ...
@@ -94,4 +94,8 @@
94 94
 */
95 95
 #undef ACK_FORKING_HACK
96 96
 
97
+/* magic cookie for transaction matching as defined in RFC3261 */
98
+#define MCOOKIE "z9hG4bK"
99
+#define MCOOKIE_LEN (sizeof(MCOOKIE)-1)
100
+
97 101
 #endif
... ...
@@ -100,6 +100,9 @@ inline struct via_body* via_body_cloner( char* new_buf,
100 100
 			translate_pointer(new_buf,org_buf,org_via->port_str.s);
101 101
 		/* params (str type) */
102 102
 		new_via->params.s=translate_pointer(new_buf,org_buf,org_via->params.s);
103
+		/* transaction id */
104
+		new_via->tid.s=
105
+			translate_pointer(new_buf, org_buf, org_via->tid.s);
103 106
 		/* comment (str type) */
104 107
 		new_via->comment.s=
105 108
 			translate_pointer(new_buf,org_buf,org_via->comment.s);
... ...
@@ -121,7 +121,7 @@ void put_on_wait(  struct cell  *Trans  )
121 121
 	}
122 122
 #endif
123 123
 #ifdef EXTRA_DEBUG
124
-	DBG("DEBUG: --- out on WAIT --- \n");
124
+	DBG("DEBUG: put on WAIT \n");
125 125
 #endif
126 126
 
127 127
 
... ...
@@ -116,6 +116,60 @@ struct cell *get_t() { return T; }
116 116
 void init_t() {global_msg_id=0; T=T_UNDEFINED;}
117 117
 
118 118
 
119
+/* transaction matching a-la RFC-3261 using transaction ID in branch
120
+ * (the function assumes there is magic cookie in branch) */
121
+
122
+static struct cell *tid_matching( int hash_index, 
123
+		struct via_body *via1, 
124
+		enum request_method skip_method)
125
+{
126
+	struct cell *p_cell;
127
+	struct sip_msg  *t_msg;
128
+
129
+
130
+	/* update parsed tid */
131
+	via1->tid.s=via1->branch->value.s+MCOOKIE_LEN;
132
+	via1->tid.len=via1->branch->value.len-MCOOKIE_LEN;
133
+
134
+	for ( p_cell = get_tm_table()->entrys[hash_index].first_cell;
135
+		p_cell; p_cell = p_cell->next_cell ) 
136
+	{
137
+		t_msg=p_cell->uas.request;
138
+		if (skip_method & t_msg->REQ_METHOD)
139
+			continue;
140
+		if (t_msg->via1->tid.len!=via1->tid.len)
141
+			continue;
142
+		if (memcmp(t_msg->via1->tid.s, via1->tid.s,
143
+				via1->tid.len)!=0)
144
+			continue;
145
+		/* ok, tid matches -- now make sure that the
146
+		 * originater matches too to avoid confusion with
147
+		 * different senders generating the same tid
148
+		 */
149
+		if (via1->host.len!=t_msg->via1->host.len)
150
+			continue;
151
+		if (memcmp(via1->host.s, t_msg->via1->host.s,
152
+					via1->host.len)!=0)
153
+			continue;
154
+		if (via1->port!=t_msg->via1->port)
155
+			continue;
156
+		if (via1->transport.len!=t_msg->via1->transport.len)
157
+			continue;
158
+		if (memcmp(via1->transport.s, t_msg->via1->transport.s,
159
+					via1->transport.len)!=0)
160
+			continue;
161
+		/* all matched -- we found the transaction ! */
162
+		DBG("DEBUG: RFC3261 transaction matched, tid=%.*s\n",
163
+			via1->tid.len, via1->tid.s);
164
+
165
+		return p_cell;
166
+	}
167
+	/* :-( ... we didn't find any */
168
+	DBG("DEBUG: RFC3261 transaction matching failed\n");
169
+	return 0;
170
+}
171
+
172
+
119 173
 /* function returns:
120 174
  *      negative - transaction wasn't found
121 175
  *			(-2 = possibly e2e ACK matched )
... ...
@@ -128,6 +182,7 @@ int t_lookup_request( struct sip_msg* p_msg , int leave_new_locked )
128 128
 	unsigned int       isACK;
129 129
 	struct sip_msg  *t_msg;
130 130
 	int ret;
131
+	struct via_param *branch;
131 132
 
132 133
 	/* parse all*/
133 134
 	if (check_transaction_quadruple(p_msg)==0)
... ...
@@ -146,10 +201,37 @@ int t_lookup_request( struct sip_msg* p_msg , int leave_new_locked )
146 146
 	DBG("t_lookup_request: start searching: hash=%d, isACK=%d\n",
147 147
 		p_msg->hash_index,isACK);
148 148
 
149
+
149 150
 	/* asume not found */
150 151
 	ret=-1;
151 152
 
152
-	/* lock the hole entry*/
153
+	/* first of all, look if there is RFC3261 magic cookie in branch; if
154
+	 * so, we can do very quick matching and skip the old-RFC bizzar
155
+	 * comparison of many header fields
156
+	 */
157
+	if (!p_msg->via1) {
158
+		LOG(L_ERR, "ERROR: t_lookup_request: no via\n");
159
+		T=0;
160
+		return 0;
161
+	}
162
+	branch=p_msg->via1->branch;
163
+	if (branch && branch->value.s && branch->value.len>MCOOKIE_LEN
164
+			&& memcmp(branch->value.s,MCOOKIE,MCOOKIE_LEN)==0) {
165
+		/* huhuhu! the cookie is there -- let's proceed fast */
166
+		LOCK_HASH(p_msg->hash_index);
167
+		p_cell=tid_matching(p_msg->hash_index, p_msg->via1, 
168
+				/* skip transactions with different
169
+				 * method; otherwise CANCEL would 
170
+				 * match the previous INVITE trans.
171
+				 */
172
+				isACK ? ~METHOD_INVITE: ~p_msg->REQ_METHOD);
173
+		if (p_cell) goto found; else goto notfound;
174
+	}
175
+
176
+	/* ok -- it's ugly old-fashioned transaction matching */
177
+	DBG("DEBUG: proceeding to pre-RFC3261 transaction matching\n");
178
+
179
+	/* lock the whole entry*/
153 180
 	LOCK_HASH(p_msg->hash_index);
154 181
 
155 182
 	/* all the transactions from the entry are compared */
... ...
@@ -250,6 +332,7 @@ int t_lookup_request( struct sip_msg* p_msg , int leave_new_locked )
250 250
 		} /* ACK */
251 251
 	} /* synonym loop */
252 252
 
253
+notfound:
253 254
 	/* no transaction found */
254 255
 	T = 0;
255 256
 	if (!leave_new_locked) {
... ...
@@ -269,7 +352,8 @@ found:
269 269
 
270 270
 
271 271
 
272
-/* function returns:
272
+/* function lookups transaction being cancelled by CANCEL in p_msg;
273
+ * it returns:
273 274
  *       0 - transaction wasn't found
274 275
  *       T - transaction found
275 276
  */
... ...
@@ -278,13 +362,40 @@ struct cell* t_lookupOriginalT(  struct sip_msg* p_msg )
278 278
 	struct cell     *p_cell;
279 279
 	unsigned int     hash_index;
280 280
 	struct sip_msg  *t_msg;
281
+	struct via_param *branch;
281 282
 
282 283
 
283 284
 	/* start searching in the table */
284 285
 	hash_index = p_msg->hash_index;
285
-	LOCK_HASH(hash_index);
286 286
 	DBG("DEBUG: t_lookupOriginalT: searching on hash entry %d\n",hash_index );
287 287
 
288
+
289
+	/* first of all, look if there is RFC3261 magic cookie in branch; if
290
+	 * so, we can do very quick matching and skip the old-RFC bizzar
291
+	 * comparison of many header fields
292
+	 */
293
+	if (!p_msg->via1) {
294
+		LOG(L_ERR, "ERROR: t_lookup_request: no via\n");
295
+		T=0;
296
+		return 0;
297
+	}
298
+	branch=p_msg->via1->branch;
299
+	if (branch && branch->value.s && branch->value.len>MCOOKIE_LEN
300
+			&& memcmp(branch->value.s,MCOOKIE,MCOOKIE_LEN)==0) {
301
+		/* huhuhu! the cookie is there -- let's proceed fast */
302
+		LOCK_HASH(hash_index);
303
+		p_cell=tid_matching(hash_index, p_msg->via1, 
304
+				/* we are seeking the original transaction --
305
+				 * skip CANCEL transactions during search
306
+				 */
307
+				METHOD_CANCEL);
308
+		if (p_cell) goto found; else goto notfound;
309
+	}
310
+
311
+	/* no cookies --proceed to old-fashioned pre-3261 t-matching */
312
+
313
+	LOCK_HASH(hash_index);
314
+
288 315
 	/* all the transactions from the entry are compared */
289 316
 	for (p_cell=get_tm_table()->entrys[hash_index].first_cell;
290 317
 		p_cell; p_cell = p_cell->next_cell )
... ...
@@ -340,19 +451,23 @@ struct cell* t_lookupOriginalT(  struct sip_msg* p_msg )
340 340
 			continue;
341 341
 
342 342
 		/* found */
343
-		DBG("DEBUG: t_lookupOriginalT: canceled transaction"
344
-			" found (%p)! \n",p_cell );
345
-		REF_UNSAFE( p_cell );
346
-		UNLOCK_HASH(hash_index);
347
-		DBG("DEBUG: t_lookupOriginalT completed\n");
348
-		return p_cell;
343
+		goto found;
349 344
 	}
350 345
 
346
+notfound:
351 347
 	/* no transaction found */
352 348
 	DBG("DEBUG: t_lookupOriginalT: no CANCEL maching found! \n" );
353 349
 	UNLOCK_HASH(hash_index);
354 350
 	DBG("DEBUG: t_lookupOriginalT completed\n");
355 351
 	return 0;
352
+
353
+found:
354
+	DBG("DEBUG: t_lookupOriginalT: canceled transaction"
355
+		" found (%p)! \n",p_cell );
356
+	REF_UNSAFE( p_cell );
357
+	UNLOCK_HASH(hash_index);
358
+	DBG("DEBUG: t_lookupOriginalT completed\n");
359
+	return p_cell;
356 360
 }
357 361
 
358 362
 
... ...
@@ -397,7 +397,7 @@ inline static void wait_handler( void *attr)
397 397
 			" called from WAIT timer\n",p_cell);
398 398
 		abort();
399 399
 	}	
400
-	DBG("DEBUG: ---------- WAIT timer hit ------- \n");
400
+	DBG("DEBUG: WAIT timer hit\n");
401 401
 #endif
402 402
 
403 403
 	/* stop cancel timers if any running */
... ...
@@ -56,7 +56,9 @@
56 56
 #define REPLY_STATUS first_line.u.reply.statuscode
57 57
 #define REPLY_CLASS(_reply) ((_reply)->REPLY_STATUS/100)
58 58
 
59
-enum { METHOD_OTHER, METHOD_INVITE, METHOD_CANCEL, METHOD_ACK, METHOD_BYE };
59
+/* number methods as power of two to allow bitmap matching */
60
+enum request_method { METHOD_INVITE=1, METHOD_CANCEL=2, METHOD_ACK=4, 
61
+	METHOD_BYE=8, METHOD_OTHER=16 };
60 62
 
61 63
 #define IFISMETHOD(methodname,firstchar)                                  \
62 64
 if (  (*tmp==(firstchar) || *tmp==((firstchar) | 32)) &&                  \
... ...
@@ -68,6 +68,7 @@ struct via_body {
68 68
 
69 69
 	     /* shortcuts to "important" params*/
70 70
 	struct via_param* branch;
71
+	str tid; /* transaction id, part of branch */
71 72
 	struct via_param* received;
72 73
 	
73 74
 	struct via_body* next; /* pointer to next via body string if