Browse code

- patch from Miklos Tirpak <miklos@iptel.org>: - tm minor fixes - tm dialog improvements - tm_binds extended (more function exported)

Andrei Pelinescu-Onciul authored on 14/11/2006 18:11:06
Showing 11 changed files
... ...
@@ -140,7 +140,9 @@ static inline int calculate_hooks(dlg_t* _d)
140 140
 	} else {
141 141
 		if (_d->rem_target.s) _d->hooks.request_uri = &_d->rem_target;
142 142
 		else _d->hooks.request_uri = &_d->rem_uri;
143
-		_d->hooks.next_hop = _d->hooks.request_uri;
143
+		
144
+		if (_d->dst_uri.s) _d->hooks.next_hop = &_d->dst_uri;
145
+		else _d->hooks.next_hop = _d->hooks.request_uri;
144 146
 	}
145 147
 
146 148
 	if ((_d->hooks.request_uri) && (_d->hooks.request_uri->s) && (_d->hooks.request_uri->len)) {
... ...
@@ -446,6 +448,11 @@ static inline int response2dlg(struct sip_msg* _m, dlg_t* _d)
446 448
 		_d->rem_target.s = 0; 
447 449
 		_d->rem_target.len = 0;
448 450
 	}
451
+	if (_d->dst_uri.s) {
452
+		shm_free(_d->dst_uri.s);
453
+		_d->dst_uri.s = 0; 
454
+		_d->dst_uri.len = 0;
455
+	}
449 456
 	if (contact.len && str_duplicate(&_d->rem_target, &contact) < 0) return -3;
450 457
 	
451 458
 	if (get_to_tag(_m, &rtag) < 0) goto err1;
... ...
@@ -601,8 +608,14 @@ static inline int dlg_confirmed_resp_uac(dlg_t* _d, struct sip_msg* _m,
601 608
 		if (get_contact_uri(_m, &contact) < 0) return -3;
602 609
 		     /* If there is a contact URI */
603 610
 		if (contact.len) {
604
-			     /* Free old remote target if any */
611
+			     /* Free old remote target and destination uri if any */
605 612
 			if (_d->rem_target.s) shm_free(_d->rem_target.s);
613
+			if (_d->dst_uri.s) {
614
+				shm_free(_d->dst_uri.s);
615
+				_d->dst_uri.s = 0;
616
+				_d->dst_uri.len = 0;
617
+			}
618
+				
606 619
 			     /* Duplicate new remote target */
607 620
 			if (str_duplicate(&_d->rem_target, &contact) < 0) return -4;
608 621
 		}
... ...
@@ -637,7 +650,7 @@ int dlg_response_uac(dlg_t* _d, struct sip_msg* _m,
637 650
 		return dlg_confirmed_resp_uac(_d, _m, is_target_refresh);
638 651
 
639 652
 	case DLG_DESTROYED:
640
-		LOG(L_ERR, "dlg_response_uac(): Cannot handle destroyed dialog\n");
653
+		LOG(L_DBG, "dlg_response_uac(): Cannot handle destroyed dialog\n");
641 654
 		return -2;
642 655
 	}
643 656
 
... ...
@@ -749,7 +762,15 @@ static inline int request2dlg(struct sip_msg* _m, dlg_t* _d)
749 762
 	}
750 763
 
751 764
 	if (get_contact_uri(_m, &contact) < 0) return -2;
752
-	if (contact.len && str_duplicate(&_d->rem_target, &contact) < 0) return -3;
765
+	if (contact.len) {
766
+		if (_d->rem_target.s) shm_free(_d->rem_target.s);
767
+		if (_d->dst_uri.s) {
768
+			shm_free(_d->dst_uri.s);
769
+			_d->dst_uri.s = 0;
770
+			_d->dst_uri.len = 0;
771
+		}
772
+		if (str_duplicate(&_d->rem_target, &contact) < 0) return -3;
773
+	}
753 774
 	
754 775
 	if (get_from_tag(_m, &rtag) < 0) goto err1;
755 776
 	if (rtag.len && str_duplicate(&_d->id.rem_tag, &rtag) < 0) goto err1;
... ...
@@ -803,9 +824,8 @@ int new_dlg_uas(struct sip_msg* _req, int _code, /*str* _tag,*/ dlg_t** _d)
803 824
 		return -1;
804 825
 	}
805 826
 
806
-	if ((_code < 200) || (_code > 299)) {
807
-		DBG("new_dlg_uas(): Not a 2xx, no dialog created\n");
808
-		return -2;
827
+	if (_code > 299) {
828
+		DBG("new_dlg_uas(): Status code >= 300, no dialog created\n");
809 829
 	}
810 830
 
811 831
 	res = (dlg_t*)shm_malloc(sizeof(dlg_t));
... ...
@@ -822,17 +842,25 @@ int new_dlg_uas(struct sip_msg* _req, int _code, /*str* _tag,*/ dlg_t** _d)
822 842
 		return -4;
823 843
 	}
824 844
 
825
-	tag.s = tm_tags;
826
-	tag.len = TOTAG_VALUE_LEN;
827
-	calc_crc_suffix(_req, tm_tag_suffix);
828
-	if (str_duplicate(&res->id.loc_tag, &tag) < 0) {
829
-		free_dlg(res);
830
-		return -5;
845
+	if (_code > 100) {
846
+		tag.s = tm_tags;
847
+		tag.len = TOTAG_VALUE_LEN;
848
+		calc_crc_suffix(_req, tm_tag_suffix);
849
+		if (str_duplicate(&res->id.loc_tag, &tag) < 0) {
850
+			free_dlg(res);
851
+			return -5;
852
+		}
831 853
 	}
832 854
 	
833 855
 	*_d = res;
834 856
 
835
-	(*_d)->state = DLG_CONFIRMED;
857
+	if (_code < 100)
858
+		(*_d)->state = DLG_NEW;
859
+	else if (_code < 200)
860
+		(*_d)->state = DLG_EARLY;
861
+	else
862
+		(*_d)->state = DLG_CONFIRMED;
863
+
836 864
 	if (calculate_hooks(*_d) < 0) {
837 865
 		LOG(L_ERR, "new_dlg_uas(): Error while calculating hooks\n");
838 866
 		free_dlg(res);
... ...
@@ -842,6 +870,46 @@ int new_dlg_uas(struct sip_msg* _req, int _code, /*str* _tag,*/ dlg_t** _d)
842 870
 	return 0;
843 871
 }
844 872
 
873
+/*
874
+ * UAS side - update dialog state and to tag
875
+ */
876
+int update_dlg_uas(dlg_t *_d, int _code, str* _tag)
877
+{
878
+	if (_d->state == DLG_CONFIRMED) {
879
+		LOG(L_ERR, "update_dlg_uas(): Dialog is already confirmed\n");
880
+		return -1;
881
+	} else if (_d->state == DLG_DESTROYED) {
882
+		LOG(L_ERR, "update_dlg_uas(): Dialog is already destroyed\n");
883
+		return -2;
884
+	}
885
+
886
+	if (_tag && _tag->s) {
887
+		if (_d->id.loc_tag.s) {
888
+			if ((_tag->len == _d->id.loc_tag.len)
889
+			&& (!memcmp(_tag->s, _d->id.loc_tag.s, _tag->len))) {
890
+				LOG(L_DBG, "update_dlg_uas(): Local tag is already set\n");
891
+			} else {
892
+				LOG(L_ERR, "update_dlg_uas(): ERROR: trying to rewrite local tag\n");
893
+				return -3;
894
+			}
895
+		} else {
896
+			if (str_duplicate(&_d->id.loc_tag, _tag) < 0) {
897
+				LOG(L_ERR, "update_dlg_uas(): Not enough memory\n");
898
+				return -4;
899
+			}
900
+		}
901
+	}
902
+
903
+	if ((100 < _code) && (_code < 200))
904
+		_d->state = DLG_EARLY;
905
+	else if (_code < 300)
906
+		_d->state = DLG_CONFIRMED;
907
+	else
908
+		_d->state = DLG_DESTROYED;
909
+
910
+	return 0;
911
+}
912
+
845 913
 /*
846 914
  * UAS side - update a dialog from a request
847 915
  */
... ...
@@ -881,6 +949,11 @@ int dlg_request_uas(dlg_t* _d, struct sip_msg* _m, target_refresh_t is_target_re
881 949
 		if (get_contact_uri(_m, &contact) < 0) return -5;
882 950
 		if (contact.len) {
883 951
 			if (_d->rem_target.s) shm_free(_d->rem_target.s);
952
+			if (_d->dst_uri.s) {
953
+				shm_free(_d->dst_uri.s);
954
+				_d->dst_uri.s = 0;
955
+				_d->dst_uri.len = 0;
956
+			}
884 957
 			if (str_duplicate(&_d->rem_target, &contact) < 0) return -6;
885 958
 		}
886 959
 
... ...
@@ -985,6 +1058,7 @@ void free_dlg(dlg_t* _d)
985 1058
 	if (_d->loc_uri.s) shm_free(_d->loc_uri.s);
986 1059
 	if (_d->rem_uri.s) shm_free(_d->rem_uri.s);
987 1060
 	if (_d->rem_target.s) shm_free(_d->rem_target.s);
1061
+	if (_d->dst_uri.s) shm_free(_d->dst_uri.s);
988 1062
 
989 1063
 	     /* Free all routes in the route set */
990 1064
 	shm_free_rr(&_d->route_set);
... ...
@@ -1008,6 +1082,7 @@ void print_dlg(FILE* out, dlg_t* _d)
1008 1082
 	fprintf(out, "loc_uri       : '%.*s'\n", _d->loc_uri.len, _d->loc_uri.s);
1009 1083
 	fprintf(out, "rem_uri       : '%.*s'\n", _d->rem_uri.len, _d->rem_uri.s);
1010 1084
 	fprintf(out, "rem_target    : '%.*s'\n", _d->rem_target.len, _d->rem_target.s);
1085
+	fprintf(out, "dst_uri       : '%.*s'\n", _d->dst_uri.len, _d->dst_uri.s);
1011 1086
 	fprintf(out, "secure:       : %d\n", _d->secure);
1012 1087
 	fprintf(out, "state         : ");
1013 1088
 	switch(_d->state) {
... ...
@@ -1028,3 +1103,33 @@ void print_dlg(FILE* out, dlg_t* _d)
1028 1103
 	
1029 1104
 	fprintf(out, "====dlg_t====\n");
1030 1105
 }
1106
+
1107
+/*
1108
+ * set dialog's request uri and destination uri (optional)
1109
+ */
1110
+int set_dlg_target(dlg_t* _d, str* _ruri, str* _duri) {
1111
+
1112
+	if (!_d || !_ruri) {
1113
+		LOG(L_ERR, "set_dlg_target(): Invalid parameter value\n");
1114
+		return -1;
1115
+	}
1116
+
1117
+	if (_d->rem_target.s) shm_free(_d->rem_target.s);
1118
+	if (_d->dst_uri.s) {
1119
+		shm_free(_d->dst_uri.s);
1120
+		_d->dst_uri.s = 0;
1121
+		_d->dst_uri.len = 0;
1122
+	}
1123
+
1124
+	if (str_duplicate(&_d->rem_target, _ruri)) return -1;
1125
+	if (_duri && _duri->len) {
1126
+		if (str_duplicate(&_d->dst_uri, _duri)) return -1;
1127
+	}
1128
+
1129
+	if (calculate_hooks(_d)) {
1130
+		LOG(L_ERR, "set_dlg_target(): Error while calculating hooks\n");
1131
+		return -1;
1132
+	}
1133
+
1134
+	return 0;
1135
+}
... ...
@@ -96,6 +96,7 @@ typedef struct dlg {
96 96
 	str loc_uri;            /* Local URI */
97 97
 	str rem_uri;            /* Remote URI */
98 98
 	str rem_target;         /* Remote target URI */
99
+	str dst_uri;		/* Destination URI */
99 100
 	unsigned char secure;   /* Secure flag -- currently not used */
100 101
 	dlg_state_t state;      /* State of the dialog */
101 102
 	rr_t* route_set;        /* Route set */
... ...
@@ -130,6 +131,11 @@ typedef int (*dlg_response_uac_f)(dlg_t* _d, struct sip_msg* _m, target_refresh_
130 131
 int new_dlg_uas(struct sip_msg* _req, int _code, /*str* _tag,*/ dlg_t** _d);
131 132
 typedef int (*new_dlg_uas_f)(struct sip_msg* _req, int _code, dlg_t** _d);
132 133
 
134
+/*
135
+ * UAS side - update dialog state and to tag
136
+ */
137
+int update_dlg_uas(dlg_t *_d, int _code, str* _tag);
138
+typedef int (*update_dlg_uas_f)(dlg_t *_d, int _code, str* _tag);
133 139
 
134 140
 /*
135 141
  * UAS side - update a dialog from a request
... ...
@@ -171,4 +177,10 @@ char* print_routeset(char* buf, dlg_t* _d);
171 177
 int w_calculate_hooks(dlg_t* _d);
172 178
 typedef int (*calculate_hooks_f)(dlg_t* _d);
173 179
 
180
+/*
181
+ * set dialog's request uri and destination uri (optional)
182
+ */
183
+int set_dlg_target(dlg_t* _d, str* _ruri, str* _duri);
184
+typedef int (*set_dlg_target_f)(dlg_t* _d, str* _ruri, str* _duri);
185
+
174 186
 #endif /* DLG_H */
... ...
@@ -67,6 +67,9 @@ void which_cancel( struct cell *t, branch_bm_t *cancel_bm );
67 67
 int cancel_uacs( struct cell *t, branch_bm_t cancel_bm, int flags );
68 68
 int cancel_branch( struct cell *t, int branch, int flags );
69 69
 
70
+typedef int(*cancel_uacs_f)( struct cell *t, branch_bm_t cancel_bm,
71
+								int flags );
72
+
70 73
 
71 74
 
72 75
 /* should be called either with the REPLY_LOCK held or if its known
... ...
@@ -66,6 +66,7 @@ int add_branch_label( struct cell *trans,
66 66
 
67 67
 /* releases T-context */
68 68
 int t_unref( struct sip_msg *p_msg);
69
+typedef int (*tunref_f)( struct sip_msg *p_msg);
69 70
 
70 71
 /* function returns:
71 72
  *      -1 - transaction wasn't found
... ...
@@ -89,6 +90,7 @@ typedef int (*tislocal_f)(struct sip_msg*);
89 90
 typedef int (*tnewtran_f)(struct sip_msg*);
90 91
 typedef int (*tget_ti_f)(struct sip_msg*, unsigned int*, unsigned int*);
91 92
 typedef int (*tlookup_ident_f)(struct cell**, unsigned int, unsigned int);
93
+typedef int (*trelease_f)(struct sip_msg*);
92 94
 
93 95
 int t_is_local(struct sip_msg*);
94 96
 int t_get_trans_ident(struct sip_msg* p_msg, unsigned int* hash_index, unsigned int* label);
... ...
@@ -676,8 +676,8 @@ void inline static free_faked_req(struct sip_msg *faked_req, struct cell *t)
676 676
 
677 677
 
678 678
 /* return 1 if a failure_route processes */
679
-static inline int run_failure_handlers(struct cell *t, struct sip_msg *rpl,
680
-											int code, int extra_flags)
679
+int run_failure_handlers(struct cell *t, struct sip_msg *rpl,
680
+					int code, int extra_flags)
681 681
 {
682 682
 	static struct sip_msg faked_req;
683 683
 	struct sip_msg *shmem_msg = t->uas.request;
... ...
@@ -1740,6 +1740,8 @@ int t_reply_with_body( struct cell *trans, unsigned int code,
1740 1740
 	s_to_tag.s = to_tag;
1741 1741
 	if(to_tag)
1742 1742
 		s_to_tag.len = strlen(to_tag);
1743
+	else
1744
+		s_to_tag.len = 0;
1743 1745
 
1744 1746
 	/* mark the transaction as replied */
1745 1747
 	if (code>=200) set_kr(REQ_RPLD);
... ...
@@ -87,6 +87,11 @@ int w_t_reply_wrp(struct sip_msg *m, unsigned int code, char *txt);
87 87
  */
88 88
 int reply_received( struct sip_msg  *p_msg ) ;
89 89
 
90
+/* return 1 if a failure_route processes */
91
+int run_failure_handlers(struct cell *t, struct sip_msg *rpl,
92
+					int code, int extra_flags);
93
+typedef int (*run_failure_handlers_f)(struct cell*, struct sip_msg*, int, int);
94
+
90 95
 
91 96
 /* Retransmits the last sent inbound reply.
92 97
  * Returns  -1 - error
... ...
@@ -114,6 +114,7 @@
114 114
 #include "t_cancel.h"
115 115
 #include "t_fifo.h"
116 116
 #include "timer.h"
117
+#include "t_msgbuilder.h"
117 118
 
118 119
 MODULE_VERSION
119 120
 
... ...
@@ -296,12 +297,18 @@ static cmd_export_t cmds[]={
296 297
 	{"new_dlg_uac",        (cmd_function)new_dlg_uac,       NO_SCRIPT,   0, 0},
297 298
 	{"dlg_response_uac",   (cmd_function)dlg_response_uac,  NO_SCRIPT,   0, 0},
298 299
 	{"new_dlg_uas",        (cmd_function)new_dlg_uas,       NO_SCRIPT,   0, 0},
300
+	{"update_dlg_uas",     (cmd_function)update_dlg_uas,    NO_SCRIPT,   0, 0},
299 301
 	{"dlg_request_uas",    (cmd_function)dlg_request_uas,   NO_SCRIPT,   0, 0},
302
+	{"set_dlg_target",     (cmd_function)set_dlg_target,    NO_SCRIPT,   0, 0},
300 303
 	{"free_dlg",           (cmd_function)free_dlg,          NO_SCRIPT,   0, 0},
301 304
 	{"print_dlg",          (cmd_function)print_dlg,         NO_SCRIPT,   0, 0},
302 305
 	{T_GETT,               (cmd_function)get_t,             NO_SCRIPT,   0, 0},
303 306
 	{"calculate_hooks",    (cmd_function)w_calculate_hooks, NO_SCRIPT,   0, 0},
304 307
 	{"t_uac",              (cmd_function)t_uac,             NO_SCRIPT,   0, 0},
308
+	{"t_uac_with_ids",     (cmd_function)t_uac_with_ids,    NO_SCRIPT,   0, 0},
309
+	{"t_unref",            (cmd_function)t_unref,           NO_SCRIPT,   0, 0},
310
+	{"run_failure_handlers", (cmd_function)run_failure_handlers, NO_SCRIPT,   0, 0},
311
+	{"cancel_uacs",        (cmd_function)cancel_uacs,       NO_SCRIPT,   0, 0},
305 312
 	{0,0,0,0,0}
306 313
 };
307 314
 
... ...
@@ -664,8 +671,10 @@ inline static int w_t_lookup_cancel(struct sip_msg* msg, char* str, char* str2)
664 671
 			/* The cell is reffed by t_lookupOriginalT, but T is not set.
665 672
 			So we must unref it before returning. */
666 673
 			UNREF(ret);
674
+			set_t(T_UNDEFINED);
667 675
 			return 1;
668 676
 		}
677
+		set_t(T_UNDEFINED);
669 678
 	} else {
670 679
 		LOG(L_WARN, "WARNING: script error t_lookup_cancel() called for non-CANCEL request\n");
671 680
 	}
... ...
@@ -896,10 +905,15 @@ inline static int w_t_reply(struct sip_msg* msg, char* p1, char* p2)
896 905
 inline static int w_t_release(struct sip_msg* msg, char* str, char* str2)
897 906
 {
898 907
 	struct cell *t;
908
+	int ret;
909
+	
899 910
 	if (t_check( msg  , 0  )==-1) return -1;
900 911
 	t=get_t();
901
-	if ( t && t!=T_UNDEFINED )
902
-		return t_release_transaction( t );
912
+	if ( t && t!=T_UNDEFINED ) {
913
+		ret = t_release_transaction( t );
914
+		t_unref(msg);
915
+		return ret;
916
+	}
903 917
 	return 1;
904 918
 }
905 919
 
... ...
@@ -133,11 +133,21 @@ int load_tm( struct tm_binds *tmb)
133 133
 		LOG( L_ERR, LOAD_ERROR "'new_dlg_uas' not found\n");
134 134
 		return -1;
135 135
 	}
136
+	if (!(tmb->update_dlg_uas=(update_dlg_uas_f)find_export
137
+	("update_dlg_uas", NO_SCRIPT, 0)) ) {
138
+		LOG( L_ERR, LOAD_ERROR "'update_dlg_uas' not found\n");
139
+		return -1;
140
+	}
136 141
 	if (!(tmb->dlg_request_uas=(dlg_request_uas_f)find_export
137 142
 	("dlg_request_uas", NO_SCRIPT, 0)) ) {
138 143
 		LOG( L_ERR, LOAD_ERROR "'dlg_request_uas' not found\n");
139 144
 		return -1;
140 145
 	}
146
+	if (!(tmb->set_dlg_target=(set_dlg_target_f)find_export
147
+	("set_dlg_target", NO_SCRIPT, 0)) ) {
148
+		LOG( L_ERR, LOAD_ERROR "'set_dlg_target' not found\n");
149
+		return -1;
150
+	}
141 151
 	if (!(tmb->free_dlg=(free_dlg_f)find_export("free_dlg", NO_SCRIPT, 0)) ) {
142 152
 		LOG( L_ERR, LOAD_ERROR "'free_dlg' not found\n");
143 153
 		return -1;
... ...
@@ -158,6 +168,28 @@ int load_tm( struct tm_binds *tmb)
158 168
 		LOG( L_ERR, LOAD_ERROR "'t_uac' not found\n");
159 169
 		return -1;
160 170
 	}
171
+	if (!(tmb->t_uac_with_ids=(t_uac_with_ids_t)find_export("t_uac_with_ids", NO_SCRIPT, 0)) ) {
172
+		LOG( L_ERR, LOAD_ERROR "'t_uac_with_ids' not found\n");
173
+		return -1;
174
+	}
175
+	if (!(tmb->t_release=(trelease_f)find_export("t_release",0,0))) {
176
+		LOG( L_ERR, LOAD_ERROR "'t_release' not found\n");
177
+		return -1;
178
+	}
179
+	if (!(tmb->t_unref=(tunref_f)find_export("t_unref",NO_SCRIPT,0))) {
180
+		LOG( L_ERR, LOAD_ERROR "'t_unref' not found\n");
181
+		return -1;
182
+	}
183
+	if (!(tmb->run_failure_handlers=
184
+	    (run_failure_handlers_f)find_export("run_failure_handlers",NO_SCRIPT,0))) {
185
+		LOG( L_ERR, LOAD_ERROR "'run_failure_handlers' not found\n");
186
+		return -1;
187
+	}
188
+	if (!(tmb->cancel_uacs=(cancel_uacs_f)find_export("cancel_uacs",NO_SCRIPT,0))) {
189
+		LOG( L_ERR, LOAD_ERROR "'cancel_uacs' not found\n");
190
+		return -1;
191
+	}
192
+
161 193
 	tmb->prepare_request_within = prepare_req_within;
162 194
 	tmb->send_prepared_request = send_prepared_request;
163 195
 	
... ...
@@ -46,6 +46,7 @@
46 46
 #include "t_lookup.h"
47 47
 #include "t_reply.h"
48 48
 #include "dlg.h"
49
+#include "t_cancel.h"
49 50
 
50 51
 /* export not usable from scripts */
51 52
 #define NO_SCRIPT	-1
... ...
@@ -94,12 +95,19 @@ struct tm_binds {
94 95
 	new_dlg_uac_f      new_dlg_uac;
95 96
 	dlg_response_uac_f dlg_response_uac;
96 97
 	new_dlg_uas_f      new_dlg_uas;
98
+	update_dlg_uas_f   update_dlg_uas;
97 99
 	dlg_request_uas_f  dlg_request_uas;
100
+	set_dlg_target_f   set_dlg_target;
98 101
 	free_dlg_f         free_dlg;
99 102
 	print_dlg_f        print_dlg;
100 103
 	tgett_f            t_gett;
101 104
 	calculate_hooks_f  calculate_hooks;
102 105
 	t_uac_t            t_uac;
106
+	t_uac_with_ids_t   t_uac_with_ids;
107
+	trelease_f         t_release;
108
+	tunref_f           t_unref;
109
+	run_failure_handlers_f run_failure_handlers;
110
+	cancel_uacs_f      cancel_uacs;
103 111
 	prepare_request_within_f  prepare_request_within;
104 112
 	send_prepared_request_f   send_prepared_request;
105 113
 	enum route_mode*   route_mode;
... ...
@@ -165,8 +165,9 @@ static inline unsigned int dlg2hash( dlg_t* dlg )
165 165
 	return hashid;
166 166
 }
167 167
 
168
-static inline int t_uac_prepare(str* method, str* headers, str* body, dlg_t* dialog,
169
-	  transaction_cb cb, void* cbp, struct retr_buf **dst_req)
168
+static inline int t_uac_prepare(str* method, str* headers, str* body, 
169
+		dlg_t* dialog, transaction_cb cb, void* cbp, struct retr_buf **dst_req,
170
+		struct cell **dst_cell)
170 171
 {
171 172
 	struct dest_info dst;
172 173
 	struct cell *new_cell;
... ...
@@ -174,19 +175,29 @@ static inline int t_uac_prepare(str* method, str* headers, str* body, dlg_t* dia
174 175
 	char* buf;
175 176
         int buf_len, ret, flags;
176 177
 	unsigned int hi;
178
+	int is_ack;
177 179
 #ifdef USE_DNS_FAILOVER
178 180
 	struct dns_srv_handle dns_h;
179 181
 #endif
180 182
 
181 183
 	ret=-1;
184
+	hi=0; /* make gcc happy */
182 185
 	/*if (dst_req) *dst_req = NULL;*/
186
+	is_ack = (((method->len == 3) && (memcmp("ACK", method->s, 3)==0)) ? 1 : 0);
183 187
 	
184 188
 	/*** added by dcm 
185 189
 	 * - needed by external ua to send a request within a dlg
186 190
 	 */
187
-	if(!dialog->hooks.next_hop && w_calculate_hooks(dialog)<0)
191
+	if (w_calculate_hooks(dialog)<0 && !dialog->hooks.next_hop)
188 192
 		goto error2;
189 193
 
194
+	if (!dialog->loc_seq.is_set) {
195
+		/* this is the first request in the dialog,
196
+		set cseq to default value now - Miklos */
197
+		dialog->loc_seq.value = DEFAULT_CSEQ;
198
+		dialog->loc_seq.is_set = 1;
199
+	}
200
+
190 201
 	DBG("DEBUG:tm:t_uac: next_hop=<%.*s>\n",dialog->hooks.next_hop->len,
191 202
 			dialog->hooks.next_hop->s);
192 203
 	/* it's a new message, so we will take the default socket */
... ...
@@ -260,10 +271,12 @@ static inline int t_uac_prepare(str* method, str* headers, str* body, dlg_t* dia
260 271
 	
261 272
 	request->dst = dst;
262 273
 
263
-	hi=dlg2hash(dialog);
264
-	LOCK_HASH(hi);
265
-	insert_into_hash_table_unsafe(new_cell, hi);
266
-	UNLOCK_HASH(hi);
274
+	if (!is_ack) {
275
+		hi=dlg2hash(dialog);
276
+		LOCK_HASH(hi);
277
+		insert_into_hash_table_unsafe(new_cell, hi);
278
+		UNLOCK_HASH(hi);
279
+	}
267 280
 
268 281
 	buf = build_uac_req(method, headers, body, dialog, 0, new_cell,
269 282
 		&buf_len, &dst);
... ...
@@ -281,13 +294,16 @@ static inline int t_uac_prepare(str* method, str* headers, str* body, dlg_t* dia
281 294
 	new_cell->nr_of_outgoings++;
282 295
 	
283 296
 	if (dst_req) *dst_req = request;
297
+	if (dst_cell) *dst_cell = new_cell;
284 298
 	
285 299
 	return 1;
286 300
 
287 301
  error1:
288
-	LOCK_HASH(hi);
289
-	remove_from_hash_table_unsafe(new_cell);
290
-	UNLOCK_HASH(hi);
302
+ 	if (!is_ack) {
303
+		LOCK_HASH(hi);
304
+		remove_from_hash_table_unsafe(new_cell);
305
+		UNLOCK_HASH(hi);
306
+	}
291 307
 	free_cell(new_cell);
292 308
 error2:
293 309
 	return ret;
... ...
@@ -314,7 +330,7 @@ int prepare_req_within(str* method, str* headers,
314 330
 	if ((method->len == 6) && (!memcmp("CANCEL", method->s, 6))) goto send;
315 331
 	dialog->loc_seq.value++; /* Increment CSeq */
316 332
  send:
317
-	return t_uac_prepare(method, headers, body, dialog, completion_cb, cbp, dst_req);
333
+	return t_uac_prepare(method, headers, body, dialog, completion_cb, cbp, dst_req, 0);
318 334
 
319 335
  err:
320 336
 	/* if (cbp) shm_free(cbp); */
... ...
@@ -323,19 +339,19 @@ int prepare_req_within(str* method, str* headers,
323 339
 	return -1;
324 340
 }
325 341
 
326
-static inline void send_prepared_request_impl(struct retr_buf *request)
342
+static inline void send_prepared_request_impl(struct retr_buf *request, int retransmit)
327 343
 {
328 344
 	if (SEND_BUFFER(request) == -1) {
329 345
 		LOG(L_ERR, "t_uac: Attempt to send to precreated request failed\n");
330 346
 	}
331 347
 	
332
-	if (start_retr(request)!=0)
348
+	if (retransmit && (start_retr(request)!=0))
333 349
 		LOG(L_CRIT, "BUG: t_uac: failed to start retr. for %p\n", request);
334 350
 }
335 351
 
336 352
 void send_prepared_request(struct retr_buf *request)
337 353
 {
338
-	send_prepared_request_impl(request);
354
+	send_prepared_request_impl(request, 1 /* retransmit */);
339 355
 }
340 356
 
341 357
 /*
... ...
@@ -345,14 +361,48 @@ int t_uac(str* method, str* headers, str* body, dlg_t* dialog,
345 361
 	  transaction_cb cb, void* cbp)
346 362
 {
347 363
 	struct retr_buf *request;
364
+	struct cell *cell;
348 365
 	int ret;
366
+	int is_ack;
349 367
 
350
-	ret = t_uac_prepare(method, headers, body, dialog, cb, cbp, &request);
368
+	ret = t_uac_prepare(method, headers, body, dialog, cb, cbp, &request, &cell);
351 369
 	if (ret < 0) return ret;
352
-	send_prepared_request_impl(request);
370
+	is_ack = (method->len == 3) && (memcmp("ACK", method->s, 3)==0) ? 1 : 0;
371
+	send_prepared_request_impl(request, !is_ack /* retransmit */);
372
+	if (cell && is_ack)
373
+		free_cell(cell);
353 374
 	return ret;
354 375
 }
355 376
 
377
+/*
378
+ * Send a request using data from the dialog structure
379
+ * ret_index and ret_label will identify the new cell
380
+ */
381
+int t_uac_with_ids(str* method, str* headers, str* body, dlg_t* dialog,
382
+	transaction_cb cb, void* cbp,
383
+	unsigned int *ret_index, unsigned int *ret_label)
384
+{
385
+	struct retr_buf *request;
386
+	struct cell *cell;
387
+	int ret;
388
+	int is_ack;
389
+
390
+	ret = t_uac_prepare(method, headers, body, dialog, cb, cbp, &request, &cell);
391
+	if (ret < 0) return ret;
392
+	is_ack = (method->len == 3) && (memcmp("ACK", method->s, 3)==0) ? 1 : 0;
393
+	send_prepared_request_impl(request, !is_ack /* retransmit */);
394
+	if (is_ack) {
395
+		if (cell) free_cell(cell);
396
+		if (ret_index && ret_label)
397
+			*ret_index = *ret_label = 0;
398
+	} else {
399
+		if (ret_index && ret_label) {
400
+			*ret_index = cell->hash_index;
401
+			*ret_label = cell->label;
402
+		}
403
+	}
404
+	return ret;
405
+}
356 406
 
357 407
 /*
358 408
  * Send a message within a dialog
... ...
@@ -364,11 +414,6 @@ int req_within(str* method, str* headers, str* body, dlg_t* dialog, transaction_
364 414
 		goto err;
365 415
 	}
366 416
 
367
-	if (dialog->state != DLG_CONFIRMED) {
368
-		LOG(L_ERR, "req_within: Dialog is not confirmed yet\n");
369
-		goto err;
370
-	}
371
-
372 417
 	if ((method->len == 3) && (!memcmp("ACK", method->s, 3))) goto send;
373 418
 	if ((method->len == 6) && (!memcmp("CANCEL", method->s, 6))) goto send;
374 419
 	dialog->loc_seq.value++; /* Increment CSeq */
... ...
@@ -51,6 +51,8 @@ typedef int (*reqwith_t)(str* m, str* h, str* b, dlg_t* d, transaction_cb c, voi
51 51
 typedef int (*reqout_t)(str* m, str* t, str* f, str* h, str* b, dlg_t** d, transaction_cb c, void* cp);
52 52
 typedef int (*req_t)(str* m, str* ruri, str* t, str* f, str* h, str* b, str *next_hop, transaction_cb c, void* cp);
53 53
 typedef int (*t_uac_t)(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb cb, void* cbp);
54
+typedef int (*t_uac_with_ids_t)(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb cb, void* cbp,
55
+		unsigned int *ret_index, unsigned int *ret_label);
54 56
 typedef int (*prepare_request_within_f)(str* method, str* headers, 
55 57
 		str* body, dlg_t* dialog, transaction_cb cb, void* cbp,
56 58
 		struct retr_buf **request_dst);
... ...
@@ -74,7 +76,12 @@ int uac_init(void);
74 76
  */
75 77
 int t_uac(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb cb, void* cbp);
76 78
 
77
-
79
+/*
80
+ * Send a request
81
+ * ret_index and ret_label will identify the new cell
82
+ */
83
+int t_uac_with_ids(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb cb, void* cbp,
84
+			unsigned int *ret_index, unsigned int *ret_label);
78 85
 /*
79 86
  * Send a message within a dialog
80 87
  */