Browse code

Added parameter to dlg_request_uas and dlg_response_uac.

This parameter specifies if it is target refresh request/response. This is
needed because TM module is not able to determine target refresh methods for
all dialog types. Only INVITE method was used as target refresh, but this is
error for non-INVITE dialogs (SUBSCRIBE/NOTIFY, ...).

If you want to behave like previous versions use TARGET_REFRESH_UNKNOWN as
value but be aware of possible problems.

Vaclav Kubart authored on 12/07/2006 09:39:20
Showing 2 changed files
... ...
@@ -366,6 +366,54 @@ static inline int get_route_set(struct sip_msg* _m, rr_t** _rs, unsigned char _o
366 366
 	return -1;
367 367
 }
368 368
 
369
+/*
370
+ * Extract method from CSeq header field
371
+ */
372
+static inline int get_cseq_method(struct sip_msg* _m, str* _method)
373
+{
374
+	if (!_m->cseq && ((parse_headers(_m, HDR_CSEQ_F, 0) == -1) || !_m->cseq)) {
375
+		LOG(L_ERR, "get_cseq_method(): Error while parsing CSeq\n");
376
+		return -1;
377
+	}
378
+
379
+	_method->s = get_cseq(_m)->method.s;
380
+	_method->len = get_cseq(_m)->method.len;
381
+	return 0;
382
+}
383
+
384
+
385
+static inline int refresh_dialog_resp(struct sip_msg* _m, 
386
+		target_refresh_t is_target_refresh)
387
+{
388
+	str method;
389
+	
390
+	switch (is_target_refresh) {
391
+		case IS_NOT_TARGET_REFRESH: 
392
+			return 0;
393
+		case IS_TARGET_REFRESH: 
394
+			return 1;
395
+		case TARGET_REFRESH_UNKNOWN: 
396
+			if (get_cseq_method(_m, &method) < 0) return 0; /* error */
397
+			if ((method.len == 6) && !memcmp("INVITE", method.s, 6)) 
398
+				return 1;
399
+			else return 0;
400
+	}
401
+	return 0;
402
+}
403
+		
404
+static inline int refresh_dialog_req(struct sip_msg* _m, target_refresh_t is_target_refresh)
405
+{
406
+	switch (is_target_refresh) {
407
+		case IS_NOT_TARGET_REFRESH: 
408
+			return 0;
409
+		case IS_TARGET_REFRESH: 
410
+			return 1;
411
+		case TARGET_REFRESH_UNKNOWN: 
412
+			return (_m->first_line.u.request.method_value == METHOD_INVITE);
413
+			break;
414
+	}
415
+	return 0;
416
+}
369 417
 
370 418
 /*
371 419
  * Extract all necessary information from a response and put it
... ...
@@ -469,6 +517,10 @@ static inline int dlg_early_resp_uac(dlg_t* _d, struct sip_msg* _m)
469 469
 		     /* We are in early state already, do nothing
470 470
 		      */
471 471
 	} else if ((code >= 200) && (code <= 299)) {
472
+		/* Warning - we can handle here response for non-initial request (for
473
+		 * example UPDATE within early INVITE/BYE dialog) and move into
474
+		 * confirmed state may be error! But this depends on dialog type... */
475
+		
472 476
 		     /* Same as in dlg_new_resp_uac */
473 477
 		     /* A final response, update the structures and transit
474 478
 		      * into DLG_CONFIRMED
... ...
@@ -492,29 +544,14 @@ static inline int dlg_early_resp_uac(dlg_t* _d, struct sip_msg* _m)
492 492
 
493 493
 
494 494
 /*
495
- * Extract method from CSeq header field
496
- */
497
-static inline int get_cseq_method(struct sip_msg* _m, str* _method)
498
-{
499
-	if (!_m->cseq && ((parse_headers(_m, HDR_CSEQ_F, 0) == -1) || !_m->cseq)) {
500
-		LOG(L_ERR, "get_cseq_method(): Error while parsing CSeq\n");
501
-		return -1;
502
-	}
503
-
504
-	_method->s = get_cseq(_m)->method.s;
505
-	_method->len = get_cseq(_m)->method.len;
506
-	return 0;
507
-}
508
-
509
-
510
-/*
511 495
  * Handle dialog in DLG_CONFIRMED state, we will be processing
512 496
  * a response to a request sent within a dialog
513 497
  */
514
-static inline int dlg_confirmed_resp_uac(dlg_t* _d, struct sip_msg* _m)
498
+static inline int dlg_confirmed_resp_uac(dlg_t* _d, struct sip_msg* _m, 
499
+		target_refresh_t is_target_refresh)
515 500
 {
516 501
 	int code;
517
-	str method, contact;
502
+	str contact;
518 503
 
519 504
 	code = _m->first_line.u.reply.statuscode;	
520 505
 
... ...
@@ -524,10 +561,6 @@ static inline int dlg_confirmed_resp_uac(dlg_t* _d, struct sip_msg* _m)
524 524
 	      * a target refresher. 
525 525
 	      */
526 526
 
527
-	     /* FIXME: Currently we support only INVITEs as target refreshers,
528
-	      * this should be generalized
529
-	      */
530
-
531 527
 	     /* IF we receive a 481 response, terminate the dialog because
532 528
 	      * the remote peer indicated that it didn't have the dialog
533 529
 	      * state anymore, signal this termination with a positive return
... ...
@@ -541,8 +574,7 @@ static inline int dlg_confirmed_resp_uac(dlg_t* _d, struct sip_msg* _m)
541 541
 	     /* Do nothing if not 2xx */
542 542
 	if ((code < 200) || (code >= 300)) return 0;
543 543
 	
544
-	if (get_cseq_method(_m, &method) < 0) return -1;
545
-	if ((method.len == 6) && !memcmp("INVITE", method.s, 6)) {
544
+	if (refresh_dialog_resp(_m, is_target_refresh)) {
546 545
 		     /* Get contact if any and update remote target */
547 546
 		if (parse_headers(_m, HDR_CONTACT_F, 0) == -1) {
548 547
 			LOG(L_ERR, "dlg_confirmed_resp_uac(): Error while parsing headers\n");
... ...
@@ -558,6 +590,8 @@ static inline int dlg_confirmed_resp_uac(dlg_t* _d, struct sip_msg* _m)
558 558
 			     /* Duplicate new remote target */
559 559
 			if (str_duplicate(&_d->rem_target, &contact) < 0) return -4;
560 560
 		}
561
+
562
+		calculate_hooks(_d);
561 563
 	}
562 564
 
563 565
 	return 0;
... ...
@@ -567,7 +601,8 @@ static inline int dlg_confirmed_resp_uac(dlg_t* _d, struct sip_msg* _m)
567 567
 /*
568 568
  * A response arrived, update dialog
569 569
  */
570
-int dlg_response_uac(dlg_t* _d, struct sip_msg* _m)
570
+int dlg_response_uac(dlg_t* _d, struct sip_msg* _m, 
571
+		target_refresh_t is_target_refresh)
571 572
 {
572 573
 	if (!_d || !_m) {
573 574
 		LOG(L_ERR, "dlg_response_uac(): Invalid parameter value\n");
... ...
@@ -583,7 +618,7 @@ int dlg_response_uac(dlg_t* _d, struct sip_msg* _m)
583 583
 		return dlg_early_resp_uac(_d, _m);
584 584
 
585 585
 	case DLG_CONFIRMED: 
586
-		return dlg_confirmed_resp_uac(_d, _m);
586
+		return dlg_confirmed_resp_uac(_d, _m, is_target_refresh);
587 587
 
588 588
 	case DLG_DESTROYED:
589 589
 		LOG(L_ERR, "dlg_response_uac(): Cannot handle destroyed dialog\n");
... ...
@@ -791,11 +826,10 @@ int new_dlg_uas(struct sip_msg* _req, int _code, /*str* _tag,*/ dlg_t** _d)
791 791
 	return 0;
792 792
 }
793 793
 
794
-
795 794
 /*
796 795
  * UAS side - update a dialog from a request
797 796
  */
798
-int dlg_request_uas(dlg_t* _d, struct sip_msg* _m)
797
+int dlg_request_uas(dlg_t* _d, struct sip_msg* _m, target_refresh_t is_target_refresh)
799 798
 {
800 799
 	str contact;
801 800
 	int cseq;
... ...
@@ -822,8 +856,7 @@ int dlg_request_uas(dlg_t* _d, struct sip_msg* _m)
822 822
 	     /* We will als update remote target URI if the message 
823 823
 	      * is target refresher
824 824
 	      */
825
-	if (_m->first_line.u.request.method_value == METHOD_INVITE) {
826
-		     /* target refresher */
825
+	if (refresh_dialog_req(_m, is_target_refresh)) { /* target refresher */
827 826
 		if (parse_headers(_m, HDR_CONTACT_F, 0) == -1) {
828 827
 			LOG(L_ERR, "dlg_request_uas(): Error while parsing headers\n");
829 828
 			return -4;
... ...
@@ -834,6 +867,9 @@ int dlg_request_uas(dlg_t* _d, struct sip_msg* _m)
834 834
 			if (_d->rem_target.s) shm_free(_d->rem_target.s);
835 835
 			if (str_duplicate(&_d->rem_target, &contact) < 0) return -6;
836 836
 		}
837
+
838
+		calculate_hooks(_d);
839
+		
837 840
 	}
838 841
 
839 842
 	return 0;
... ...
@@ -105,6 +105,11 @@ typedef struct dlg {
105 105
 				 */
106 106
 } dlg_t;
107 107
 
108
+typedef enum {
109
+	IS_TARGET_REFRESH,
110
+	IS_NOT_TARGET_REFRESH,
111
+	TARGET_REFRESH_UNKNOWN
112
+} target_refresh_t;
108 113
 
109 114
 /*
110 115
  * Create a new dialog
... ...
@@ -116,8 +121,8 @@ typedef int (*new_dlg_uac_f)(str* _cid, str* _ltag, unsigned int _lseq, str* _lu
116 116
 /*
117 117
  * A response arrived, update dialog
118 118
  */
119
-int dlg_response_uac(dlg_t* _d, struct sip_msg* _m);
120
-typedef int (*dlg_response_uac_f)(dlg_t* _d, struct sip_msg* _m);
119
+int dlg_response_uac(dlg_t* _d, struct sip_msg* _m, target_refresh_t is_target_refresh);
120
+typedef int (*dlg_response_uac_f)(dlg_t* _d, struct sip_msg* _m, target_refresh_t is_target_refresh);
121 121
 
122 122
 /*
123 123
  * Establishing a new dialog, UAS side
... ...
@@ -129,8 +134,8 @@ typedef int (*new_dlg_uas_f)(struct sip_msg* _req, int _code, dlg_t** _d);
129 129
 /*
130 130
  * UAS side - update a dialog from a request
131 131
  */
132
-int dlg_request_uas(dlg_t* _d, struct sip_msg* _m);
133
-typedef int (*dlg_request_uas_f)(dlg_t* _d, struct sip_msg* _m);
132
+int dlg_request_uas(dlg_t* _d, struct sip_msg* _m, target_refresh_t is_target_request);
133
+typedef int (*dlg_request_uas_f)(dlg_t* _d, struct sip_msg* _m, target_refresh_t is_target_request);
134 134
 
135 135
 
136 136
 /*