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 446
 		_d->rem_target.s = 0; 
447 447
 		_d->rem_target.len = 0;
448 448
 	}
449
+	if (_d->dst_uri.s) {
450
+		shm_free(_d->dst_uri.s);
451
+		_d->dst_uri.s = 0; 
452
+		_d->dst_uri.len = 0;
453
+	}
449 454
 	if (contact.len && str_duplicate(&_d->rem_target, &contact) < 0) return -3;
450 455
 	
451 456
 	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 601
 		if (get_contact_uri(_m, &contact) < 0) return -3;
602 602
 		     /* If there is a contact URI */
603 603
 		if (contact.len) {
604
-			     /* Free old remote target if any */
604
+			     /* Free old remote target and destination uri if any */
605 605
 			if (_d->rem_target.s) shm_free(_d->rem_target.s);
606
+			if (_d->dst_uri.s) {
607
+				shm_free(_d->dst_uri.s);
608
+				_d->dst_uri.s = 0;
609
+				_d->dst_uri.len = 0;
610
+			}
611
+				
606 612
 			     /* Duplicate new remote target */
607 613
 			if (str_duplicate(&_d->rem_target, &contact) < 0) return -4;
608 614
 		}
... ...
@@ -637,7 +650,7 @@ int dlg_response_uac(dlg_t* _d, struct sip_msg* _m,
637 637
 		return dlg_confirmed_resp_uac(_d, _m, is_target_refresh);
638 638
 
639 639
 	case DLG_DESTROYED:
640
-		LOG(L_ERR, "dlg_response_uac(): Cannot handle destroyed dialog\n");
640
+		LOG(L_DBG, "dlg_response_uac(): Cannot handle destroyed dialog\n");
641 641
 		return -2;
642 642
 	}
643 643
 
... ...
@@ -749,7 +762,15 @@ static inline int request2dlg(struct sip_msg* _m, dlg_t* _d)
749 749
 	}
750 750
 
751 751
 	if (get_contact_uri(_m, &contact) < 0) return -2;
752
-	if (contact.len && str_duplicate(&_d->rem_target, &contact) < 0) return -3;
752
+	if (contact.len) {
753
+		if (_d->rem_target.s) shm_free(_d->rem_target.s);
754
+		if (_d->dst_uri.s) {
755
+			shm_free(_d->dst_uri.s);
756
+			_d->dst_uri.s = 0;
757
+			_d->dst_uri.len = 0;
758
+		}
759
+		if (str_duplicate(&_d->rem_target, &contact) < 0) return -3;
760
+	}
753 761
 	
754 762
 	if (get_from_tag(_m, &rtag) < 0) goto err1;
755 763
 	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 803
 		return -1;
804 804
 	}
805 805
 
806
-	if ((_code < 200) || (_code > 299)) {
807
-		DBG("new_dlg_uas(): Not a 2xx, no dialog created\n");
808
-		return -2;
806
+	if (_code > 299) {
807
+		DBG("new_dlg_uas(): Status code >= 300, no dialog created\n");
809 808
 	}
810 809
 
811 810
 	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 822
 		return -4;
823 823
 	}
824 824
 
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;
825
+	if (_code > 100) {
826
+		tag.s = tm_tags;
827
+		tag.len = TOTAG_VALUE_LEN;
828
+		calc_crc_suffix(_req, tm_tag_suffix);
829
+		if (str_duplicate(&res->id.loc_tag, &tag) < 0) {
830
+			free_dlg(res);
831
+			return -5;
832
+		}
831 833
 	}
832 834
 	
833 835
 	*_d = res;
834 836
 
835
-	(*_d)->state = DLG_CONFIRMED;
837
+	if (_code < 100)
838
+		(*_d)->state = DLG_NEW;
839
+	else if (_code < 200)
840
+		(*_d)->state = DLG_EARLY;
841
+	else
842
+		(*_d)->state = DLG_CONFIRMED;
843
+
836 844
 	if (calculate_hooks(*_d) < 0) {
837 845
 		LOG(L_ERR, "new_dlg_uas(): Error while calculating hooks\n");
838 846
 		free_dlg(res);
... ...
@@ -843,6 +871,46 @@ int new_dlg_uas(struct sip_msg* _req, int _code, /*str* _tag,*/ dlg_t** _d)
843 843
 }
844 844
 
845 845
 /*
846
+ * UAS side - update dialog state and to tag
847
+ */
848
+int update_dlg_uas(dlg_t *_d, int _code, str* _tag)
849
+{
850
+	if (_d->state == DLG_CONFIRMED) {
851
+		LOG(L_ERR, "update_dlg_uas(): Dialog is already confirmed\n");
852
+		return -1;
853
+	} else if (_d->state == DLG_DESTROYED) {
854
+		LOG(L_ERR, "update_dlg_uas(): Dialog is already destroyed\n");
855
+		return -2;
856
+	}
857
+
858
+	if (_tag && _tag->s) {
859
+		if (_d->id.loc_tag.s) {
860
+			if ((_tag->len == _d->id.loc_tag.len)
861
+			&& (!memcmp(_tag->s, _d->id.loc_tag.s, _tag->len))) {
862
+				LOG(L_DBG, "update_dlg_uas(): Local tag is already set\n");
863
+			} else {
864
+				LOG(L_ERR, "update_dlg_uas(): ERROR: trying to rewrite local tag\n");
865
+				return -3;
866
+			}
867
+		} else {
868
+			if (str_duplicate(&_d->id.loc_tag, _tag) < 0) {
869
+				LOG(L_ERR, "update_dlg_uas(): Not enough memory\n");
870
+				return -4;
871
+			}
872
+		}
873
+	}
874
+
875
+	if ((100 < _code) && (_code < 200))
876
+		_d->state = DLG_EARLY;
877
+	else if (_code < 300)
878
+		_d->state = DLG_CONFIRMED;
879
+	else
880
+		_d->state = DLG_DESTROYED;
881
+
882
+	return 0;
883
+}
884
+
885
+/*
846 886
  * UAS side - update a dialog from a request
847 887
  */
848 888
 int dlg_request_uas(dlg_t* _d, struct sip_msg* _m, target_refresh_t is_target_refresh)
... ...
@@ -881,6 +949,11 @@ int dlg_request_uas(dlg_t* _d, struct sip_msg* _m, target_refresh_t is_target_re
881 881
 		if (get_contact_uri(_m, &contact) < 0) return -5;
882 882
 		if (contact.len) {
883 883
 			if (_d->rem_target.s) shm_free(_d->rem_target.s);
884
+			if (_d->dst_uri.s) {
885
+				shm_free(_d->dst_uri.s);
886
+				_d->dst_uri.s = 0;
887
+				_d->dst_uri.len = 0;
888
+			}
884 889
 			if (str_duplicate(&_d->rem_target, &contact) < 0) return -6;
885 890
 		}
886 891
 
... ...
@@ -985,6 +1058,7 @@ void free_dlg(dlg_t* _d)
985 985
 	if (_d->loc_uri.s) shm_free(_d->loc_uri.s);
986 986
 	if (_d->rem_uri.s) shm_free(_d->rem_uri.s);
987 987
 	if (_d->rem_target.s) shm_free(_d->rem_target.s);
988
+	if (_d->dst_uri.s) shm_free(_d->dst_uri.s);
988 989
 
989 990
 	     /* Free all routes in the route set */
990 991
 	shm_free_rr(&_d->route_set);
... ...
@@ -1008,6 +1082,7 @@ void print_dlg(FILE* out, dlg_t* _d)
1008 1008
 	fprintf(out, "loc_uri       : '%.*s'\n", _d->loc_uri.len, _d->loc_uri.s);
1009 1009
 	fprintf(out, "rem_uri       : '%.*s'\n", _d->rem_uri.len, _d->rem_uri.s);
1010 1010
 	fprintf(out, "rem_target    : '%.*s'\n", _d->rem_target.len, _d->rem_target.s);
1011
+	fprintf(out, "dst_uri       : '%.*s'\n", _d->dst_uri.len, _d->dst_uri.s);
1011 1012
 	fprintf(out, "secure:       : %d\n", _d->secure);
1012 1013
 	fprintf(out, "state         : ");
1013 1014
 	switch(_d->state) {
... ...
@@ -1028,3 +1103,33 @@ void print_dlg(FILE* out, dlg_t* _d)
1028 1028
 	
1029 1029
 	fprintf(out, "====dlg_t====\n");
1030 1030
 }
1031
+
1032
+/*
1033
+ * set dialog's request uri and destination uri (optional)
1034
+ */
1035
+int set_dlg_target(dlg_t* _d, str* _ruri, str* _duri) {
1036
+
1037
+	if (!_d || !_ruri) {
1038
+		LOG(L_ERR, "set_dlg_target(): Invalid parameter value\n");
1039
+		return -1;
1040
+	}
1041
+
1042
+	if (_d->rem_target.s) shm_free(_d->rem_target.s);
1043
+	if (_d->dst_uri.s) {
1044
+		shm_free(_d->dst_uri.s);
1045
+		_d->dst_uri.s = 0;
1046
+		_d->dst_uri.len = 0;
1047
+	}
1048
+
1049
+	if (str_duplicate(&_d->rem_target, _ruri)) return -1;
1050
+	if (_duri && _duri->len) {
1051
+		if (str_duplicate(&_d->dst_uri, _duri)) return -1;
1052
+	}
1053
+
1054
+	if (calculate_hooks(_d)) {
1055
+		LOG(L_ERR, "set_dlg_target(): Error while calculating hooks\n");
1056
+		return -1;
1057
+	}
1058
+
1059
+	return 0;
1060
+}
... ...
@@ -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 130
 int new_dlg_uas(struct sip_msg* _req, int _code, /*str* _tag,*/ dlg_t** _d);
131 131
 typedef int (*new_dlg_uas_f)(struct sip_msg* _req, int _code, dlg_t** _d);
132 132
 
133
+/*
134
+ * UAS side - update dialog state and to tag
135
+ */
136
+int update_dlg_uas(dlg_t *_d, int _code, str* _tag);
137
+typedef int (*update_dlg_uas_f)(dlg_t *_d, int _code, str* _tag);
133 138
 
134 139
 /*
135 140
  * UAS side - update a dialog from a request
... ...
@@ -171,4 +177,10 @@ char* print_routeset(char* buf, dlg_t* _d);
171 171
 int w_calculate_hooks(dlg_t* _d);
172 172
 typedef int (*calculate_hooks_f)(dlg_t* _d);
173 173
 
174
+/*
175
+ * set dialog's request uri and destination uri (optional)
176
+ */
177
+int set_dlg_target(dlg_t* _d, str* _ruri, str* _duri);
178
+typedef int (*set_dlg_target_f)(dlg_t* _d, str* _ruri, str* _duri);
179
+
174 180
 #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 89
 typedef int (*tnewtran_f)(struct sip_msg*);
90 90
 typedef int (*tget_ti_f)(struct sip_msg*, unsigned int*, unsigned int*);
91 91
 typedef int (*tlookup_ident_f)(struct cell**, unsigned int, unsigned int);
92
+typedef int (*trelease_f)(struct sip_msg*);
92 93
 
93 94
 int t_is_local(struct sip_msg*);
94 95
 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 296
 	{"new_dlg_uac",        (cmd_function)new_dlg_uac,       NO_SCRIPT,   0, 0},
297 297
 	{"dlg_response_uac",   (cmd_function)dlg_response_uac,  NO_SCRIPT,   0, 0},
298 298
 	{"new_dlg_uas",        (cmd_function)new_dlg_uas,       NO_SCRIPT,   0, 0},
299
+	{"update_dlg_uas",     (cmd_function)update_dlg_uas,    NO_SCRIPT,   0, 0},
299 300
 	{"dlg_request_uas",    (cmd_function)dlg_request_uas,   NO_SCRIPT,   0, 0},
301
+	{"set_dlg_target",     (cmd_function)set_dlg_target,    NO_SCRIPT,   0, 0},
300 302
 	{"free_dlg",           (cmd_function)free_dlg,          NO_SCRIPT,   0, 0},
301 303
 	{"print_dlg",          (cmd_function)print_dlg,         NO_SCRIPT,   0, 0},
302 304
 	{T_GETT,               (cmd_function)get_t,             NO_SCRIPT,   0, 0},
303 305
 	{"calculate_hooks",    (cmd_function)w_calculate_hooks, NO_SCRIPT,   0, 0},
304 306
 	{"t_uac",              (cmd_function)t_uac,             NO_SCRIPT,   0, 0},
307
+	{"t_uac_with_ids",     (cmd_function)t_uac_with_ids,    NO_SCRIPT,   0, 0},
308
+	{"t_unref",            (cmd_function)t_unref,           NO_SCRIPT,   0, 0},
309
+	{"run_failure_handlers", (cmd_function)run_failure_handlers, NO_SCRIPT,   0, 0},
310
+	{"cancel_uacs",        (cmd_function)cancel_uacs,       NO_SCRIPT,   0, 0},
305 311
 	{0,0,0,0,0}
306 312
 };
307 313
 
... ...
@@ -664,8 +671,10 @@ inline static int w_t_lookup_cancel(struct sip_msg* msg, char* str, char* str2)
664 664
 			/* The cell is reffed by t_lookupOriginalT, but T is not set.
665 665
 			So we must unref it before returning. */
666 666
 			UNREF(ret);
667
+			set_t(T_UNDEFINED);
667 668
 			return 1;
668 669
 		}
670
+		set_t(T_UNDEFINED);
669 671
 	} else {
670 672
 		LOG(L_WARN, "WARNING: script error t_lookup_cancel() called for non-CANCEL request\n");
671 673
 	}
... ...
@@ -896,10 +905,15 @@ inline static int w_t_reply(struct sip_msg* msg, char* p1, char* p2)
896 896
 inline static int w_t_release(struct sip_msg* msg, char* str, char* str2)
897 897
 {
898 898
 	struct cell *t;
899
+	int ret;
900
+	
899 901
 	if (t_check( msg  , 0  )==-1) return -1;
900 902
 	t=get_t();
901
-	if ( t && t!=T_UNDEFINED )
902
-		return t_release_transaction( t );
903
+	if ( t && t!=T_UNDEFINED ) {
904
+		ret = t_release_transaction( t );
905
+		t_unref(msg);
906
+		return ret;
907
+	}
903 908
 	return 1;
904 909
 }
905 910
 
... ...
@@ -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 158
 		LOG( L_ERR, LOAD_ERROR "'t_uac' not found\n");
159 159
 		return -1;
160 160
 	}
161
+	if (!(tmb->t_uac_with_ids=(t_uac_with_ids_t)find_export("t_uac_with_ids", NO_SCRIPT, 0)) ) {
162
+		LOG( L_ERR, LOAD_ERROR "'t_uac_with_ids' not found\n");
163
+		return -1;
164
+	}
165
+	if (!(tmb->t_release=(trelease_f)find_export("t_release",0,0))) {
166
+		LOG( L_ERR, LOAD_ERROR "'t_release' not found\n");
167
+		return -1;
168
+	}
169
+	if (!(tmb->t_unref=(tunref_f)find_export("t_unref",NO_SCRIPT,0))) {
170
+		LOG( L_ERR, LOAD_ERROR "'t_unref' not found\n");
171
+		return -1;
172
+	}
173
+	if (!(tmb->run_failure_handlers=
174
+	    (run_failure_handlers_f)find_export("run_failure_handlers",NO_SCRIPT,0))) {
175
+		LOG( L_ERR, LOAD_ERROR "'run_failure_handlers' not found\n");
176
+		return -1;
177
+	}
178
+	if (!(tmb->cancel_uacs=(cancel_uacs_f)find_export("cancel_uacs",NO_SCRIPT,0))) {
179
+		LOG( L_ERR, LOAD_ERROR "'cancel_uacs' not found\n");
180
+		return -1;
181
+	}
182
+
161 183
 	tmb->prepare_request_within = prepare_req_within;
162 184
 	tmb->send_prepared_request = send_prepared_request;
163 185
 	
... ...
@@ -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 94
 	new_dlg_uac_f      new_dlg_uac;
95 95
 	dlg_response_uac_f dlg_response_uac;
96 96
 	new_dlg_uas_f      new_dlg_uas;
97
+	update_dlg_uas_f   update_dlg_uas;
97 98
 	dlg_request_uas_f  dlg_request_uas;
99
+	set_dlg_target_f   set_dlg_target;
98 100
 	free_dlg_f         free_dlg;
99 101
 	print_dlg_f        print_dlg;
100 102
 	tgett_f            t_gett;
101 103
 	calculate_hooks_f  calculate_hooks;
102 104
 	t_uac_t            t_uac;
105
+	t_uac_with_ids_t   t_uac_with_ids;
106
+	trelease_f         t_release;
107
+	tunref_f           t_unref;
108
+	run_failure_handlers_f run_failure_handlers;
109
+	cancel_uacs_f      cancel_uacs;
103 110
 	prepare_request_within_f  prepare_request_within;
104 111
 	send_prepared_request_f   send_prepared_request;
105 112
 	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 174
 	char* buf;
175 175
         int buf_len, ret, flags;
176 176
 	unsigned int hi;
177
+	int is_ack;
177 178
 #ifdef USE_DNS_FAILOVER
178 179
 	struct dns_srv_handle dns_h;
179 180
 #endif
180 181
 
181 182
 	ret=-1;
183
+	hi=0; /* make gcc happy */
182 184
 	/*if (dst_req) *dst_req = NULL;*/
185
+	is_ack = (((method->len == 3) && (memcmp("ACK", method->s, 3)==0)) ? 1 : 0);
183 186
 	
184 187
 	/*** added by dcm 
185 188
 	 * - needed by external ua to send a request within a dlg
186 189
 	 */
187
-	if(!dialog->hooks.next_hop && w_calculate_hooks(dialog)<0)
190
+	if (w_calculate_hooks(dialog)<0 && !dialog->hooks.next_hop)
188 191
 		goto error2;
189 192
 
193
+	if (!dialog->loc_seq.is_set) {
194
+		/* this is the first request in the dialog,
195
+		set cseq to default value now - Miklos */
196
+		dialog->loc_seq.value = DEFAULT_CSEQ;
197
+		dialog->loc_seq.is_set = 1;
198
+	}
199
+
190 200
 	DBG("DEBUG:tm:t_uac: next_hop=<%.*s>\n",dialog->hooks.next_hop->len,
191 201
 			dialog->hooks.next_hop->s);
192 202
 	/* 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 260
 	
261 261
 	request->dst = dst;
262 262
 
263
-	hi=dlg2hash(dialog);
264
-	LOCK_HASH(hi);
265
-	insert_into_hash_table_unsafe(new_cell, hi);
266
-	UNLOCK_HASH(hi);
263
+	if (!is_ack) {
264
+		hi=dlg2hash(dialog);
265
+		LOCK_HASH(hi);
266
+		insert_into_hash_table_unsafe(new_cell, hi);
267
+		UNLOCK_HASH(hi);
268
+	}
267 269
 
268 270
 	buf = build_uac_req(method, headers, body, dialog, 0, new_cell,
269 271
 		&buf_len, &dst);
... ...
@@ -281,13 +294,16 @@ static inline int t_uac_prepare(str* method, str* headers, str* body, dlg_t* dia
281 281
 	new_cell->nr_of_outgoings++;
282 282
 	
283 283
 	if (dst_req) *dst_req = request;
284
+	if (dst_cell) *dst_cell = new_cell;
284 285
 	
285 286
 	return 1;
286 287
 
287 288
  error1:
288
-	LOCK_HASH(hi);
289
-	remove_from_hash_table_unsafe(new_cell);
290
-	UNLOCK_HASH(hi);
289
+ 	if (!is_ack) {
290
+		LOCK_HASH(hi);
291
+		remove_from_hash_table_unsafe(new_cell);
292
+		UNLOCK_HASH(hi);
293
+	}
291 294
 	free_cell(new_cell);
292 295
 error2:
293 296
 	return ret;
... ...
@@ -314,7 +330,7 @@ int prepare_req_within(str* method, str* headers,
314 314
 	if ((method->len == 6) && (!memcmp("CANCEL", method->s, 6))) goto send;
315 315
 	dialog->loc_seq.value++; /* Increment CSeq */
316 316
  send:
317
-	return t_uac_prepare(method, headers, body, dialog, completion_cb, cbp, dst_req);
317
+	return t_uac_prepare(method, headers, body, dialog, completion_cb, cbp, dst_req, 0);
318 318
 
319 319
  err:
320 320
 	/* if (cbp) shm_free(cbp); */
... ...
@@ -323,19 +339,19 @@ int prepare_req_within(str* method, str* headers,
323 323
 	return -1;
324 324
 }
325 325
 
326
-static inline void send_prepared_request_impl(struct retr_buf *request)
326
+static inline void send_prepared_request_impl(struct retr_buf *request, int retransmit)
327 327
 {
328 328
 	if (SEND_BUFFER(request) == -1) {
329 329
 		LOG(L_ERR, "t_uac: Attempt to send to precreated request failed\n");
330 330
 	}
331 331
 	
332
-	if (start_retr(request)!=0)
332
+	if (retransmit && (start_retr(request)!=0))
333 333
 		LOG(L_CRIT, "BUG: t_uac: failed to start retr. for %p\n", request);
334 334
 }
335 335
 
336 336
 void send_prepared_request(struct retr_buf *request)
337 337
 {
338
-	send_prepared_request_impl(request);
338
+	send_prepared_request_impl(request, 1 /* retransmit */);
339 339
 }
340 340
 
341 341
 /*
... ...
@@ -345,14 +361,48 @@ int t_uac(str* method, str* headers, str* body, dlg_t* dialog,
345 345
 	  transaction_cb cb, void* cbp)
346 346
 {
347 347
 	struct retr_buf *request;
348
+	struct cell *cell;
348 349
 	int ret;
350
+	int is_ack;
349 351
 
350
-	ret = t_uac_prepare(method, headers, body, dialog, cb, cbp, &request);
352
+	ret = t_uac_prepare(method, headers, body, dialog, cb, cbp, &request, &cell);
351 353
 	if (ret < 0) return ret;
352
-	send_prepared_request_impl(request);
354
+	is_ack = (method->len == 3) && (memcmp("ACK", method->s, 3)==0) ? 1 : 0;
355
+	send_prepared_request_impl(request, !is_ack /* retransmit */);
356
+	if (cell && is_ack)
357
+		free_cell(cell);
353 358
 	return ret;
354 359
 }
355 360
 
361
+/*
362
+ * Send a request using data from the dialog structure
363
+ * ret_index and ret_label will identify the new cell
364
+ */
365
+int t_uac_with_ids(str* method, str* headers, str* body, dlg_t* dialog,
366
+	transaction_cb cb, void* cbp,
367
+	unsigned int *ret_index, unsigned int *ret_label)
368
+{
369
+	struct retr_buf *request;
370
+	struct cell *cell;
371
+	int ret;
372
+	int is_ack;
373
+
374
+	ret = t_uac_prepare(method, headers, body, dialog, cb, cbp, &request, &cell);
375
+	if (ret < 0) return ret;
376
+	is_ack = (method->len == 3) && (memcmp("ACK", method->s, 3)==0) ? 1 : 0;
377
+	send_prepared_request_impl(request, !is_ack /* retransmit */);
378
+	if (is_ack) {
379
+		if (cell) free_cell(cell);
380
+		if (ret_index && ret_label)
381
+			*ret_index = *ret_label = 0;
382
+	} else {
383
+		if (ret_index && ret_label) {
384
+			*ret_index = cell->hash_index;
385
+			*ret_label = cell->label;
386
+		}
387
+	}
388
+	return ret;
389
+}
356 390
 
357 391
 /*
358 392
  * Send a message within a dialog
... ...
@@ -364,11 +414,6 @@ int req_within(str* method, str* headers, str* body, dlg_t* dialog, transaction_
364 364
 		goto err;
365 365
 	}
366 366
 
367
-	if (dialog->state != DLG_CONFIRMED) {
368
-		LOG(L_ERR, "req_within: Dialog is not confirmed yet\n");
369
-		goto err;
370
-	}
371
-
372 367
 	if ((method->len == 3) && (!memcmp("ACK", method->s, 3))) goto send;
373 368
 	if ((method->len == 6) && (!memcmp("CANCEL", method->s, 6))) goto send;
374 369
 	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 74
  */
75 75
 int t_uac(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb cb, void* cbp);
76 76
 
77
-
77
+/*
78
+ * Send a request
79
+ * ret_index and ret_label will identify the new cell
80
+ */
81
+int t_uac_with_ids(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb cb, void* cbp,
82
+			unsigned int *ret_index, unsigned int *ret_label);
78 83
 /*
79 84
  * Send a message within a dialog
80 85
  */