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 182
 	unsigned int       isACK;
129 183
 	struct sip_msg  *t_msg;
130 184
 	int ret;
185
+	struct via_param *branch;
131 186
 
132 187
 	/* parse all*/
133 188
 	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 201
 	DBG("t_lookup_request: start searching: hash=%d, isACK=%d\n",
147 202
 		p_msg->hash_index,isACK);
148 203
 
204
+
149 205
 	/* asume not found */
150 206
 	ret=-1;
151 207
 
152
-	/* lock the hole entry*/
208
+	/* first of all, look if there is RFC3261 magic cookie in branch; if
209
+	 * so, we can do very quick matching and skip the old-RFC bizzar
210
+	 * comparison of many header fields
211
+	 */
212
+	if (!p_msg->via1) {
213
+		LOG(L_ERR, "ERROR: t_lookup_request: no via\n");
214
+		T=0;
215
+		return 0;
216
+	}
217
+	branch=p_msg->via1->branch;
218
+	if (branch && branch->value.s && branch->value.len>MCOOKIE_LEN
219
+			&& memcmp(branch->value.s,MCOOKIE,MCOOKIE_LEN)==0) {
220
+		/* huhuhu! the cookie is there -- let's proceed fast */
221
+		LOCK_HASH(p_msg->hash_index);
222
+		p_cell=tid_matching(p_msg->hash_index, p_msg->via1, 
223
+				/* skip transactions with different
224
+				 * method; otherwise CANCEL would 
225
+				 * match the previous INVITE trans.
226
+				 */
227
+				isACK ? ~METHOD_INVITE: ~p_msg->REQ_METHOD);
228
+		if (p_cell) goto found; else goto notfound;
229
+	}
230
+
231
+	/* ok -- it's ugly old-fashioned transaction matching */
232
+	DBG("DEBUG: proceeding to pre-RFC3261 transaction matching\n");
233
+
234
+	/* lock the whole entry*/
153 235
 	LOCK_HASH(p_msg->hash_index);
154 236
 
155 237
 	/* 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 332
 		} /* ACK */
251 333
 	} /* synonym loop */
252 334
 
335
+notfound:
253 336
 	/* no transaction found */
254 337
 	T = 0;
255 338
 	if (!leave_new_locked) {
... ...
@@ -269,7 +352,8 @@ found:
269 352
 
270 353
 
271 354
 
272
-/* function returns:
355
+/* function lookups transaction being cancelled by CANCEL in p_msg;
356
+ * it returns:
273 357
  *       0 - transaction wasn't found
274 358
  *       T - transaction found
275 359
  */
... ...
@@ -278,13 +362,40 @@ struct cell* t_lookupOriginalT(  struct sip_msg* p_msg )
278 362
 	struct cell     *p_cell;
279 363
 	unsigned int     hash_index;
280 364
 	struct sip_msg  *t_msg;
365
+	struct via_param *branch;
281 366
 
282 367
 
283 368
 	/* start searching in the table */
284 369
 	hash_index = p_msg->hash_index;
285
-	LOCK_HASH(hash_index);
286 370
 	DBG("DEBUG: t_lookupOriginalT: searching on hash entry %d\n",hash_index );
287 371
 
372
+
373
+	/* first of all, look if there is RFC3261 magic cookie in branch; if
374
+	 * so, we can do very quick matching and skip the old-RFC bizzar
375
+	 * comparison of many header fields
376
+	 */
377
+	if (!p_msg->via1) {
378
+		LOG(L_ERR, "ERROR: t_lookup_request: no via\n");
379
+		T=0;
380
+		return 0;
381
+	}
382
+	branch=p_msg->via1->branch;
383
+	if (branch && branch->value.s && branch->value.len>MCOOKIE_LEN
384
+			&& memcmp(branch->value.s,MCOOKIE,MCOOKIE_LEN)==0) {
385
+		/* huhuhu! the cookie is there -- let's proceed fast */
386
+		LOCK_HASH(hash_index);
387
+		p_cell=tid_matching(hash_index, p_msg->via1, 
388
+				/* we are seeking the original transaction --
389
+				 * skip CANCEL transactions during search
390
+				 */
391
+				METHOD_CANCEL);
392
+		if (p_cell) goto found; else goto notfound;
393
+	}
394
+
395
+	/* no cookies --proceed to old-fashioned pre-3261 t-matching */
396
+
397
+	LOCK_HASH(hash_index);
398
+
288 399
 	/* all the transactions from the entry are compared */
289 400
 	for (p_cell=get_tm_table()->entrys[hash_index].first_cell;
290 401
 		p_cell; p_cell = p_cell->next_cell )
... ...
@@ -340,19 +451,23 @@ struct cell* t_lookupOriginalT(  struct sip_msg* p_msg )
340 451
 			continue;
341 452
 
342 453
 		/* 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;
454
+		goto found;
349 455
 	}
350 456
 
457
+notfound:
351 458
 	/* no transaction found */
352 459
 	DBG("DEBUG: t_lookupOriginalT: no CANCEL maching found! \n" );
353 460
 	UNLOCK_HASH(hash_index);
354 461
 	DBG("DEBUG: t_lookupOriginalT completed\n");
355 462
 	return 0;
463
+
464
+found:
465
+	DBG("DEBUG: t_lookupOriginalT: canceled transaction"
466
+		" found (%p)! \n",p_cell );
467
+	REF_UNSAFE( p_cell );
468
+	UNLOCK_HASH(hash_index);
469
+	DBG("DEBUG: t_lookupOriginalT completed\n");
470
+	return p_cell;
356 471
 }
357 472
 
358 473
 
... ...
@@ -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