Browse code

- dialog support added - new functions for sending messages within and outside a dialog - bugfixes - neverending fifo functions split in smaller pieces

Jan Janak authored on 30/04/2003 18:50:58
Showing 20 changed files
... ...
@@ -7,6 +7,6 @@
7 7
 
8 8
 auto_gen=
9 9
 NAME=tm.so
10
-LIBS= 
10
+LIBS=
11 11
 
12 12
 include ../../Makefile.modules
... ...
@@ -92,4 +92,7 @@
92 92
 /* to-tag separator for stateful processing */
93 93
 #define TM_TAG_SEPARATOR '-'
94 94
 
95
+/* FIFO substitution character */
96
+#define SUBST_CHAR '!'
97
+
95 98
 #endif
... ...
@@ -41,6 +41,8 @@
41 41
 #include "../../ut.h"
42 42
 #include "../../config.h"
43 43
 #include "dlg.h"
44
+#include "t_reply.h"
45
+#include "../../parser/parser_f.h"
44 46
 
45 47
 
46 48
 #define NORMAL_ORDER 0  /* Create route set in normal order - UAS */
... ...
@@ -53,6 +55,31 @@
53 55
 #define ROUTE_SEPARATOR_LEN (sizeof(ROUTE_SEPARATOR) - 1)
54 56
 
55 57
 
58
+/*** Temporary hack ! */
59
+/*
60
+ * This function skips name part
61
+ * uri parsed by parse_contact must be used
62
+ * (the uri must not contain any leading or
63
+ *  trailing part and if angle bracket were
64
+ *  used, right angle bracket must be the
65
+ *  last character in the string)
66
+ *
67
+ * _s will be modified so it should be a tmp
68
+ * copy
69
+ */
70
+void get_raw_uri(str* _s)
71
+{
72
+        char* aq;
73
+        
74
+        if (_s->s[_s->len - 1] == '>') {
75
+                aq = find_not_quoted(_s, '<');
76
+                _s->len -= aq - _s->s + 2;
77
+                _s->s = aq + 1;
78
+        }
79
+}
80
+
81
+
82
+
56 83
 /*
57 84
  * Make a copy of a str structure using shm_malloc
58 85
  */
... ...
@@ -110,6 +137,19 @@ static inline int calculate_hooks(dlg_t* _d)
110 137
 		_d->hooks.next_hop = _d->hooks.request_uri;
111 138
 	}
112 139
 
140
+	if ((_d->hooks.request_uri) && (_d->hooks.request_uri->s) && (_d->hooks.request_uri->len)) {
141
+		_d->hooks.ru.s = _d->hooks.request_uri->s;
142
+		_d->hooks.ru.len = _d->hooks.request_uri->len;
143
+		_d->hooks.request_uri = &_d->hooks.ru;
144
+		get_raw_uri(_d->hooks.request_uri);
145
+	}
146
+	if ((_d->hooks.next_hop) && (_d->hooks.next_hop->s) && (_d->hooks.next_hop->len)) {
147
+		_d->hooks.nh.s = _d->hooks.next_hop->s;
148
+		_d->hooks.nh.len = _d->hooks.next_hop->len;
149
+		_d->hooks.next_hop = &_d->hooks.nh;
150
+		get_raw_uri(_d->hooks.next_hop);
151
+	}
152
+
113 153
 	return 0;
114 154
 }
115 155
 
... ...
@@ -275,7 +315,6 @@ static inline int get_route_set(struct sip_msg* _m, rr_t** _rs, unsigned char _o
275 315
 					LOG(L_ERR, "get_route_set(): Error while duplicating rr_t\n");
276 316
 					goto error;
277 317
 				}
278
-				
279 318
 				if (_order == NORMAL_ORDER) {
280 319
 					if (!*_rs) *_rs = t;
281 320
 					if (last) last->next = t;
... ...
@@ -310,7 +349,7 @@ static inline int response2dlg(struct sip_msg* _m, dlg_t* _d)
310 349
 
311 350
 	     /* Parse the whole message, we will need all Record-Route headers */
312 351
 	if (parse_headers(_m, HDR_EOH, 0) == -1) {
313
-		LOG(L_ERR, "dlg_new_resp_uac(): Error while parsing headers\n");
352
+		LOG(L_ERR, "response2dlg(): Error while parsing headers\n");
314 353
 		return -1;
315 354
 	}
316 355
 	
... ...
@@ -558,7 +597,7 @@ static inline int get_cseq_value(struct sip_msg* _m, unsigned int* _cs)
558 597
  */
559 598
 static inline int get_dlg_uri(struct hdr_field* _h, str* _s)
560 599
 {
561
-	struct to_param* ptr;
600
+	struct to_param* ptr, *prev;
562 601
 	struct to_body* body;
563 602
 	char* tag = 0; /* Makes gcc happy */
564 603
 	int tag_len = 0, len;
... ...
@@ -575,35 +614,42 @@ static inline int get_dlg_uri(struct hdr_field* _h, str* _s)
575 614
 	body = (struct to_body*)_h->parsed;
576 615
 
577 616
 	ptr = body->param_lst;
617
+	prev = 0;
578 618
 	while(ptr) {
579 619
 		if (ptr->type == TAG_PARAM) break;
620
+		prev = ptr;
580 621
 		ptr = ptr->next;
581 622
 	}
582 623
 
583 624
 	if (ptr) {
584
-	     /* Tag param found */
585
-		tag = ptr->name.s;
625
+		     /* Tag param found */
626
+		if (prev) {
627
+			tag = prev->value.s + prev->value.len;
628
+		} else {
629
+			tag = body->body.s + body->body.len;
630
+		}
631
+		
586 632
 		if (ptr->next) {
587 633
 			tag_len = ptr->next->name.s - tag;
588 634
 		} else {
589
-			tag_len = body->body.s + body->body.len - tag;
635
+			tag_len = _h->body.s + _h->body.len - tag;
590 636
 		}
591 637
 	}
592 638
 
593
-	_s->s = shm_malloc(body->body.len - tag_len);
639
+	_s->s = shm_malloc(_h->body.len - tag_len);
594 640
 	if (!_s->s) {
595 641
 		LOG(L_ERR, "get_dlg_uri(): No memory left\n");
596 642
 		return -1;
597 643
 	}
598 644
 
599 645
 	if (tag_len) {
600
-		len = tag - body->body.s;
601
-		memcpy(_s->s, body->body.s, len);
602
-		memcpy(_s->s + len, tag + tag_len, body->body.len - len - tag_len);
603
-		_s->len = body->body.len - tag_len;
646
+		len = tag - _h->body.s;
647
+		memcpy(_s->s, _h->body.s, len);
648
+		memcpy(_s->s + len, tag + tag_len, _h->body.len - len - tag_len);
649
+		_s->len = _h->body.len - tag_len;
604 650
 	} else {
605
-		memcpy(_s->s, body->body.s, body->body.len);
606
-		_s->len = body->body.len;
651
+		memcpy(_s->s, _h->body.s, _h->body.len);
652
+		_s->len = _h->body.len;
607 653
 	}
608 654
 
609 655
 	return 0;
... ...
@@ -668,11 +714,12 @@ static inline int request2dlg(struct sip_msg* _m, dlg_t* _d)
668 714
 /*
669 715
  * Establishing a new dialog, UAS side
670 716
  */
671
-int new_dlg_uas(struct sip_msg* _req, int _code, str* _tag, dlg_t** _d)
717
+int new_dlg_uas(struct sip_msg* _req, int _code, /*str* _tag,*/ dlg_t** _d)
672 718
 {
673 719
 	dlg_t* res;
720
+	str tag;
674 721
 
675
-	if (!_req || !_tag || !_d) {
722
+	if (!_req || /*!_tag ||*/ !_d) {
676 723
 		LOG(L_ERR, "new_dlg_uas(): Invalid parameter value\n");
677 724
 		return -1;
678 725
 	}
... ...
@@ -695,11 +742,12 @@ int new_dlg_uas(struct sip_msg* _req, int _code, str* _tag, dlg_t** _d)
695 742
 		return -4;
696 743
 	}
697 744
 
698
-	if (_tag->len) {
699
-		if (str_duplicate(&res->id.loc_tag, _tag) < 0) {
700
-			free_dlg(res);
701
-			return -5;
702
-		}
745
+	tag.s = tm_tags;
746
+	tag.len = TOTAG_VALUE_LEN;
747
+	calc_crc_suffix(_req, tm_tag_suffix);
748
+	if (str_duplicate(&res->id.loc_tag, &tag) < 0) {
749
+		free_dlg(res);
750
+		return -5;
703 751
 	}
704 752
 	
705 753
 	*_d = res;
... ...
@@ -77,6 +77,8 @@ typedef struct dlg_id {
77 77
  * message within dialog
78 78
  */
79 79
 typedef struct dlg_hooks {
80
+	str ru;
81
+	str nh;
80 82
 	str* request_uri;   /* This should be put into Request-URI */
81 83
 	str* next_hop;      /* Where the message should be really sent */
82 84
 	rr_t* first_route;  /* First route to be printed into the message */
... ...
@@ -108,36 +110,41 @@ typedef struct dlg {
108 110
  * Create a new dialog
109 111
  */
110 112
 int new_dlg_uac(str* _cid, str* _ltag, unsigned int _lseq, str* _luri, str* _ruri, dlg_t** _d);
113
+typedef int (*new_dlg_uac_f)(str* _cid, str* _ltag, unsigned int _lseq, str* _luri, str* _ruri, dlg_t** _d);
111 114
 
112 115
 
113 116
 /*
114 117
  * A response arrived, update dialog
115 118
  */
116 119
 int dlg_response_uac(dlg_t* _d, struct sip_msg* _m);
117
-
120
+typedef int (*dlg_response_uac_f)(dlg_t* _d, struct sip_msg* _m);
118 121
 
119 122
 /*
120 123
  * Establishing a new dialog, UAS side
121 124
  */
122
-int new_dlg_uas(struct sip_msg* _req, int _code, str* _tag, dlg_t** _d);
125
+int new_dlg_uas(struct sip_msg* _req, int _code, /*str* _tag,*/ dlg_t** _d);
126
+typedef int (*new_dlg_uas_f)(struct sip_msg* _req, int _code, dlg_t** _d);
123 127
 
124 128
 
125 129
 /*
126 130
  * UAS side - update a dialog from a request
127 131
  */
128 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);
129 134
 
130 135
 
131 136
 /*
132 137
  * Destroy a dialog state
133 138
  */
134 139
 void free_dlg(dlg_t* _d);
140
+typedef void (*free_dlg_f)(dlg_t* _d);
135 141
 
136 142
 
137 143
 /*
138 144
  * Print a dialog structure, just for debugging
139 145
  */
140 146
 void print_dlg(FILE* out, dlg_t* _d);
147
+typedef void (*print_dlg_f)(FILE* out, dlg_t* _d);
141 148
 
142 149
 
143 150
 /*
... ...
@@ -94,7 +94,7 @@ void cancel_branch( struct cell *t, int branch )
94 94
 
95 95
 	if (t->uac[branch].last_received<100) {
96 96
 		DBG("DEBUG: cancel_branch: no response ever received: "
97
-			"giving up on cancel\n");
97
+		    "giving up on cancel\n");
98 98
 		return;
99 99
 	}
100 100
 
... ...
@@ -219,7 +219,7 @@ int add_uac( struct cell *t, struct sip_msg *request, str *uri, str* next_hop,
219 219
 
220 220
 	/* now message printing starts ... */
221 221
 	shbuf=print_uac_request( t, request, branch, uri, 
222
-		&len, send_sock, proxy->proto);
222
+		&len, send_sock, proxy->proto );
223 223
 	if (!shbuf) {
224 224
 		ret=ser_error=E_OUT_OF_MEM;
225 225
 		goto error01;
... ...
@@ -45,7 +45,7 @@ typedef int (*taddblind_f)( /*struct cell *t */ );
45 45
 int t_replicate(struct sip_msg *p_msg, struct proxy_l * proxy, int proto);
46 46
 char *print_uac_request( struct cell *t, struct sip_msg *i_req,
47 47
     int branch, str *uri, unsigned int *len, struct socket_info *send_sock,
48
-	enum sip_protos proto);
48
+    enum sip_protos proto);
49 49
 void e2e_cancel( struct sip_msg *cancel_msg, struct cell *t_cancel, struct cell *t_invite );
50 50
 int e2e_cancel_branch( struct sip_msg *cancel_msg, struct cell *t_cancel, struct cell *t_invite, int branch );
51 51
 int add_uac(	struct cell *t, struct sip_msg *request, str *uri, str* next_hop,
... ...
@@ -989,9 +989,10 @@ static inline int new_t(struct sip_msg *p_msg)
989 989
 */
990 990
 int t_newtran( struct sip_msg* p_msg )
991 991
 {
992
-
993 992
 	int lret, my_err;
994 993
 
994
+	ret=1;
995
+
995 996
 	/* is T still up-to-date ? */
996 997
 	DBG("DEBUG: t_addifnew: msg id=%d , global msg id=%d ,"
997 998
 		" T on entrance=%p\n",p_msg->id,global_msg_id,T);
... ...
@@ -1161,7 +1162,7 @@ int t_lookup_ident(struct cell ** trans, unsigned int hash_index, unsigned int l
1161 1162
     {
1162 1163
 		if(p_cell->label == label){
1163 1164
 			REF_UNSAFE(p_cell);
1164
-    		UNLOCK_HASH(hash_index);
1165
+    			UNLOCK_HASH(hash_index);
1165 1166
 			set_t(p_cell);
1166 1167
 			*trans=p_cell;
1167 1168
 			DBG("DEBUG: t_lookup_ident: transaction found\n");
... ...
@@ -31,7 +31,7 @@
31 31
  * ----------
32 32
  * 2003-01-27  next baby-step to removing ZT - PRESERVE_ZT (jiri)
33 33
  * 2003-02-13  build_uac_request uses proto (andrei)
34
- * 2003-02-28 scratchpad compatibility abandoned (jiri)
34
+ * 2003-02-28  scratchpad compatibility abandoned (jiri)
35 35
  * 2003-04-14  build_local no longer checks reply status as it
36 36
  *             is now called before reply status is updated to
37 37
  *             avoid late ACK sending (jiri)
... ...
@@ -177,188 +177,262 @@ error:
177 177
 }
178 178
 
179 179
 
180
-
181
-char *build_uac_request_dlg(str* msg,           /* Method */
182
-			    str* ruri,          /* Request-URI */
183
-			    str* to,            /* To */
184
-			    str* from,          /* From */
185
-			    str* totag,         /* To header tag */
186
-			    str* fromtag,       /* From header tag */
187
-			    unsigned int cseq,  /* CSeq number */
188
-			    str* callid,        /* Call-ID */
189
-			    str* headers,       /* Headers to be appended */
190
-			    str* body,          /* Body of the message */
191
-			    int branch,         /* Branch */
192
-			    struct cell *t,     
193
-			    unsigned int *len,
194
-				struct socket_info* send_sock
195
-				)
180
+/*
181
+ * Convert lenght of body into asciiz
182
+ */
183
+static inline int print_content_length(str* dest, str* body)
196 184
 {
197
-	char *via, *buf, *w, content_len[10], cseq_str[10], branch_buf[MAX_BRANCH_PARAM_LEN];
198
-	char *tmp;
199
-	int content_len_len, cseq_str_len, branch_len;
200
-	str branch_str;
201
-	unsigned int via_len;
185
+	static char content_length[10];
186
+	int len;
187
+	char* tmp;
202 188
 
203
-	buf=0;
204
-	content_len_len = 0; /* Makes gcc happy */
205
-
206
-	     /* 
207
-	      * Print Content-Length
208
-	      */
189
+	     /* Print Content-Length */
209 190
 	if (body) {
210
-		tmp=int2str(body->len, &content_len_len);
211
-		if (content_len_len>=sizeof(content_len)) {
212
-			LOG(L_ERR, "ERROR: build_uac_request_dlg: content_len too big\n");
213
-			return 0;
191
+		tmp = int2str(body->len, &len);
192
+		if (len >= sizeof(content_length)) {
193
+			LOG(L_ERR, "ERROR: print_content_length: content_len too big\n");
194
+			return -1;
214 195
 		}
215
-		memcpy(content_len, tmp, content_len_len); 
196
+		memcpy(content_length, tmp, len); 
197
+		dest->s = content_length;
198
+		dest->len = len;
199
+	} else {
200
+		dest->s = 0;
201
+		dest->len = 0;
216 202
 	}
217
-	
218
-	     /* 
219
-	      * Print CSeq 
220
-	      */
221
-	tmp=int2str(cseq, &cseq_str_len);
222
-	if (cseq_str_len >= sizeof(cseq_str)) {
223
-		LOG(L_ERR, "ERROR: build_uac_request_dlg: cseq too big\n");
224
-		return 0;
203
+	return 0;
204
+}
205
+
206
+
207
+/*
208
+ * Convert CSeq number into asciiz
209
+ */
210
+static inline int print_cseq_num(str* _s, dlg_t* _d)
211
+{
212
+	static char cseq[10];
213
+	char* tmp;
214
+	int len;
215
+
216
+	tmp = int2str(_d->loc_seq.value, &len);
217
+	if (len >= sizeof(cseq)) {
218
+		LOG(L_ERR, "print_cseq_num: cseq too big\n");
219
+		return -1;
225 220
 	}
226
-	memcpy(cseq_str, tmp, cseq_str_len);
227 221
 	
228
-	*len = msg->len + 1 + ruri->len + 1 + SIP_VERSION_LEN + CRLF_LEN;
222
+	memcpy(cseq, tmp, len);
223
+	_s->s = cseq;
224
+	_s->len = len;
225
+	return 0;
226
+}
229 227
 
230
-	if (!t_calc_branch(t, branch, branch_buf, &branch_len)) {
231
-		LOG(L_ERR, "ERROR: build_uac_request_dlg: branch calculation failed\n");
232
-		goto error;
228
+
229
+/*
230
+ * Create Via header
231
+ */
232
+static inline int assemble_via(str* dest, struct cell* t, struct socket_info* sock, int branch)
233
+{
234
+	static char branch_buf[MAX_BRANCH_PARAM_LEN];
235
+	char* via;
236
+	int len, via_len;
237
+	str branch_str;
238
+
239
+	if (!t_calc_branch(t, branch, branch_buf, &len)) {
240
+		LOG(L_ERR, "ERROR: build_via: branch calculation failed\n");
241
+		return -1;
233 242
 	}
234 243
 	
235
-	branch_str.s=branch_buf;
236
-	branch_str.len=branch_len;
237
-	via = via_builder(&via_len, send_sock,
238
-			&branch_str, 0, send_sock->proto);
244
+	branch_str.s = branch_buf;
245
+	branch_str.len = len;
246
+
247
+	printf("!!!proto: %d\n", sock->proto);
248
+
249
+	via = via_builder(&via_len, sock, &branch_str, 0, sock->proto);
239 250
 	if (!via) {
240
-		LOG(L_ERR, "ERROR: build_uac_request_dlg: via building failed\n");
241
-		goto error;
251
+		LOG(L_ERR, "build_via: via building failed\n");
252
+		return -2;
242 253
 	}
243 254
 	
244
-	*len += via_len;
245
-	
246
-	/* header names and separators */
247
-	*len +=   TO_LEN + CRLF_LEN
248
-		+ FROM_LEN + CRLF_LEN
249
-		+ CSEQ_LEN + CRLF_LEN
250
-		+ CALLID_LEN + CRLF_LEN
251
-		+ ((body) ? (CONTENT_LENGTH_LEN + CRLF_LEN) : 0)
252
-		+ (server_signature ? USER_AGENT_LEN + CRLF_LEN : 0)
253
-		+ CRLF_LEN; /* EoM */
254
-	
255
-	     /* header field value and body length */
256
-	*len +=   to->len + 
257
-			((totag && totag->len) ? (TOTAG_LEN + totag->len) : 0) /* To */
258
-		+ from->len +  /* From */
259
-			((fromtag && fromtag->len) ? FROMTAG_LEN + fromtag->len:0)
260
-		+ cseq_str_len + 1 + msg->len                        /* CSeq */
261
-		+ callid->len                                        /* Call-ID */
262
-		+ ((body) ? (content_len_len) : 0)                   /* Content-Length */
263
-		+ ((headers) ? (headers->len) : 0)                   /* Headers */
264
-		+ ((body) ? (body->len) : 0);                        /* Body */
265
-	
266
-	buf = shm_malloc(*len + 1);
267
-	if (!buf) {
268
-		LOG(L_ERR, "ERROR: build_uac_request_dlg: no shmem\n");
269
-		goto error1;
270
-	}
271
-	
272
-	w = buf;
255
+	dest->s = via;
256
+	dest->len = via_len;
257
+	return 0;
258
+}
259
+
273 260
 
274
-	     /* First line */
275
-	memapp(w, msg->s, msg->len); 
261
+/*
262
+ * Print Request-URI
263
+ */
264
+static inline char* print_request_uri(char* w, str* method, dlg_t* dialog, struct cell* t, int branch)
265
+{
266
+	memapp(w, method->s, method->len); 
276 267
 	memapp(w, " ", 1); 
277 268
 
278 269
 	t->uac[branch].uri.s = w; 
279
-	t->uac[branch].uri.len = ruri->len;
270
+	t->uac[branch].uri.len = dialog->hooks.request_uri->len;
280 271
 
281
-	memapp(w, ruri->s, ruri->len); 
272
+	memapp(w, dialog->hooks.request_uri->s, dialog->hooks.request_uri->len); 
282 273
 	memapp(w, " " SIP_VERSION CRLF, 1 + SIP_VERSION_LEN + CRLF_LEN);
283 274
 
284
-	     /* First Via */
285
-	memapp(w, via, via_len);
275
+	return w;
276
+}
277
+
286 278
 
287
-	     /* To */
279
+/*
280
+ * Print To header field
281
+ */
282
+static inline char* print_to(char* w, dlg_t* dialog, struct cell* t)
283
+{
288 284
 	t->to.s = w;
289
-	t->to.len= TO_LEN+to->len+CRLF_LEN;
285
+	t->to.len = TO_LEN + dialog->rem_uri.len + CRLF_LEN;
286
+
290 287
 	memapp(w, TO, TO_LEN);
291
-	memapp(w, to->s, to->len);
292
-	if (totag && totag->len ) {
293
-		t->to.len += TOTAG_LEN + totag->len ;
288
+	memapp(w, dialog->rem_uri.s, dialog->rem_uri.len);
289
+
290
+	if (dialog->id.rem_tag.len) {
291
+		t->to.len += TOTAG_LEN + dialog->id.rem_tag.len ;
294 292
 		memapp(w, TOTAG, TOTAG_LEN);
295
-		memapp(w, totag->s, totag->len);
293
+		memapp(w, dialog->id.rem_tag.s, dialog->id.rem_tag.len);
296 294
 	}
295
+
297 296
 	memapp(w, CRLF, CRLF_LEN);
297
+	return w;
298
+}
299
+
298 300
 
299
-	     /* From */
301
+/*
302
+ * Print From header field
303
+ */
304
+static inline char* print_from(char* w, dlg_t* dialog, struct cell* t)
305
+{
300 306
 	t->from.s = w;
301
-	t->from.len = FROM_LEN + from->len + CRLF_LEN;
307
+	t->from.len = FROM_LEN + dialog->loc_uri.len + CRLF_LEN;
308
+
302 309
 	memapp(w, FROM, FROM_LEN);
303
-	memapp(w, from->s, from->len);
304
-  	if (fromtag && fromtag->len ) { 
305
-		t->from.len+= FROMTAG_LEN + fromtag->len;
310
+	memapp(w, dialog->loc_uri.s, dialog->loc_uri.len);
311
+
312
+	if (dialog->id.loc_tag.len) {
313
+		t->from.len += FROMTAG_LEN + dialog->id.loc_tag.len;
306 314
 		memapp(w, FROMTAG, FROMTAG_LEN);
307
-		memapp(w, fromtag->s, fromtag->len);
315
+		memapp(w, dialog->id.loc_tag.s, dialog->id.loc_tag.len);
308 316
 	}
317
+
309 318
 	memapp(w, CRLF, CRLF_LEN);
310
-	
311
-	     /* CSeq */
319
+	return w;
320
+}
321
+
322
+
323
+/*
324
+ * Print CSeq header field
325
+ */
326
+static inline char* print_cseq(char* w, str* cseq, str* method, struct cell* t)
327
+{
312 328
 	t->cseq_n.s = w; 
313 329
 	/* don't include method name and CRLF -- subsequent
314 330
 	 * local reuqests ACK/CANCEl will add their own */
315
-	t->cseq_n.len = CSEQ_LEN + cseq_str_len; 
331
+	t->cseq_n.len = CSEQ_LEN + cseq->len; 
316 332
 
317 333
 	memapp(w, CSEQ, CSEQ_LEN);
318
-	memapp(w, cseq_str, cseq_str_len);
334
+	memapp(w, cseq->s, cseq->len);
319 335
 	memapp(w, " ", 1);
320
-	memapp(w, msg->s, msg->len);
336
+	memapp(w, method->s, method->len);
337
+	return w;
338
+}
339
+
321 340
 
322
-	     /* Call-ID */
341
+/*
342
+ * Print Call-ID header field
343
+ */
344
+static inline char* print_callid(char* w, dlg_t* dialog, struct cell* t)
345
+{
323 346
 	t->callid.s = w + CRLF_LEN; 
324
-	t->callid.len = CALLID_LEN + callid->len + CRLF_LEN;
347
+	t->callid.len = CALLID_LEN + dialog->id.call_id.len + CRLF_LEN;
325 348
 	memapp(w, CRLF CALLID, CRLF_LEN + CALLID_LEN);
326
-	memapp(w, callid->s, callid->len);
349
+	memapp(w, dialog->id.call_id.s, dialog->id.call_id.len);
327 350
 	memapp(w, CRLF, CRLF_LEN);
351
+	return w;
352
+}
353
+
354
+
355
+/*
356
+ * Create a request
357
+ */
358
+char* build_uac_req(str* method, str* headers, str* body, dlg_t* dialog, int branch, 
359
+			struct cell *t, int* len, struct socket_info* send_sock)
360
+{
361
+	char* buf, *w;
362
+	str content_length, cseq, via;
363
+
364
+	if (!method || !dialog) {
365
+		LOG(L_ERR, "build_uac_req(): Invalid parameter value\n");
366
+		return 0;
367
+	}
368
+	if (print_content_length(&content_length, body) < 0) {
369
+		LOG(L_ERR, "build_uac_req(): Error while printing content-length\n");
370
+		return 0;
371
+	}
372
+	if (print_cseq_num(&cseq, dialog) < 0) {
373
+		LOG(L_ERR, "build_uac_req(): Error while printing CSeq number\n");
374
+		return 0;
375
+	}
376
+	*len = method->len + 1 + dialog->hooks.request_uri->len + 1 + SIP_VERSION_LEN + CRLF_LEN;
377
+
378
+	if (assemble_via(&via, t, send_sock, branch) < 0) {
379
+		LOG(L_ERR, "build_uac_req(): Error while assembling Via\n");
380
+		return 0;
381
+	}
382
+	*len += via.len;
383
+
384
+	*len += TO_LEN + dialog->rem_uri.len
385
+		+ (dialog->id.rem_tag.len ? (TOTAG_LEN + dialog->id.rem_tag.len) : 0) + CRLF_LEN;    /* To */
386
+	*len += FROM_LEN + dialog->loc_uri.len
387
+		+ (dialog->id.loc_tag.len ? (FROMTAG_LEN + dialog->id.loc_tag.len) : 0) + CRLF_LEN;  /* From */
388
+	*len += CALLID_LEN + dialog->id.call_id.len + CRLF_LEN;                                      /* Call-ID */
389
+	*len += CSEQ_LEN + cseq.len + 1 + method->len + CRLF_LEN;                                    /* CSeq */
390
+	*len += calculate_routeset_length(dialog);                                                   /* Route set */
391
+	*len += (body ? (CONTENT_LENGTH_LEN + content_length.len + CRLF_LEN) : 0);                   /* Content-Length */
392
+	*len += (server_signature ? (USER_AGENT_LEN + CRLF_LEN) : 0);                                /* Signature */
393
+	*len += (headers ? headers->len : 0);                                                        /* Additional headers */
394
+	*len += (body ? body->len : 0);                                                              /* Message body */
395
+	*len += CRLF_LEN;                                                                            /* End of Header */
396
+
397
+	buf = shm_malloc(*len + 1);
398
+	if (!buf) {
399
+		LOG(L_ERR, "build_uac_req(): no shmem\n");
400
+		goto error;
401
+	}
328 402
 	
403
+	w = buf;
404
+
405
+	w = print_request_uri(w, method, dialog, t, branch);  /* Request-URI */
406
+	memapp(w, via.s, via.len);                            /* Top-most Via */
407
+	w = print_to(w, dialog, t);                           /* To */
408
+	w = print_from(w, dialog, t);                         /* From */
409
+	w = print_cseq(w, &cseq, method, t);                  /* CSeq */
410
+	w = print_callid(w, dialog, t);                       /* Call-ID */
411
+	w = print_routeset(w, dialog);                        /* Route set */
412
+
329 413
 	     /* Content-Length */
330 414
 	if (body) {
331 415
 		memapp(w, CONTENT_LENGTH, CONTENT_LENGTH_LEN);
332
-		memapp(w, content_len, content_len_len);
416
+		memapp(w, content_length.s, content_length.len);
333 417
 		memapp(w, CRLF, CRLF_LEN);
334 418
 	}
335 419
 	
336 420
 	     /* Server signature */
337
-	if (server_signature) {
338
-		memapp(w, USER_AGENT CRLF, USER_AGENT_LEN + CRLF_LEN);
339
-	}
340
-
341
-	     /* Headers */
342
-	if (headers) {
343
-		memapp(w, headers->s, headers->len);
344
-	}
345
-
346
-	     /* EoH */
421
+	if (server_signature) memapp(w, USER_AGENT CRLF, USER_AGENT_LEN + CRLF_LEN);
422
+	if (headers) memapp(w, headers->s, headers->len);
347 423
 	memapp(w, CRLF, CRLF_LEN);
348
-	
349
-	     /* Body */
350
-	if (body) {
351
-		memapp(w, body->s, body->len);
352
-	}
424
+     	if (body) memapp(w, body->s, body->len);
353 425
 
354 426
 #ifdef EXTRA_DEBUG
355 427
 	if (w-buf != *len ) abort();
356 428
 #endif
357
-	
358
- error1:
359
-	pkg_free(via);	
360
- error:
429
+
430
+	pkg_free(via.s);
361 431
 	return buf;
432
+
433
+ error:
434
+	pkg_free(via.s);
435
+	return 0;
362 436
 }
363 437
 
364 438
 
... ...
@@ -31,8 +31,8 @@
31 31
 #define _MSGBUILDER_H
32 32
 
33 33
 #include "../../ip_addr.h"
34
-
35 34
 #include "defs.h"
35
+#include "dlg.h"
36 36
 
37 37
 
38 38
 #define CSEQ "CSeq: "
... ...
@@ -71,21 +71,11 @@ char *build_uac_request(  str msg_type, str dst, str from,
71 71
 	struct cell *t, unsigned int *len);
72 72
 
73 73
 
74
-char *build_uac_request_dlg(str* msg,            /* Method */
75
-	                    str* ruri,           /* Request-URI */
76
-	                    str* to,             /* To header field w/o tag */
77
-	                    str* from,           /* From header field w/o tag */
78
-	                    str* totag,          /* To tag */
79
-	                    str* fromtag,        /* From tag */
80
-	                    unsigned int cseq,  /* CSeq number */
81
-	                    str* callid,         /* Call-ID */
82
-	                    str* headers,        /* Headers to be appended including CRLF */
83
-	                    str* body,           /* Body of the message */
84
-	                    int branch,         /* Branch */
85
-	                    struct cell *t,
86
-	                    unsigned int *len,
87
-						struct socket_info *send_sock
88
-	                   );
74
+/*
75
+ * Create a request
76
+ */
77
+char* build_uac_req(str* method, str* headers, str* body, dlg_t* dialog, int branch, 
78
+		    struct cell *t, int* len, struct socket_info* send_sock);
89 79
 
90 80
 
91 81
 int t_calc_branch(struct cell *t,
... ...
@@ -83,7 +83,7 @@ enum route_mode rmode=MODE_REQUEST;
83 83
 /* private place where we create to-tags for replies */
84 84
 /* janakj: made public, I need to access this value to store it in dialogs */
85 85
 char tm_tags[TOTAG_VALUE_LEN];
86
-static char *tm_tag_suffix;
86
+char *tm_tag_suffix;
87 87
 
88 88
 /* where to go if there is no positive reply */
89 89
 static int goto_on_negative=0;
... ...
@@ -52,6 +52,7 @@ enum rps {
52 52
 };
53 53
 
54 54
 extern char tm_tags[TOTAG_VALUE_LEN];
55
+extern char *tm_tag_suffix;
55 56
 
56 57
 enum route_mode { MODE_REQUEST=1, MODE_ONREPLY, MODE_ONFAILURE };
57 58
 extern enum route_mode rmode;
... ...
@@ -90,14 +90,14 @@
90 90
 #include "ut.h"
91 91
 #include "t_reply.h"
92 92
 #include "uac.h"
93
+#include "uac_fifo.h"
93 94
 #include "t_fwd.h"
94 95
 #include "t_lookup.h"
95 96
 #include "t_stats.h"
97
+#include "callid.h"
96 98
 
97 99
 MODULE_VERSION
98 100
 
99
-
100
-
101 101
 inline static int w_t_check(struct sip_msg* msg, char* str, char* str2);
102 102
 inline static int w_t_reply(struct sip_msg* msg, char* str, char* str2);
103 103
 
... ...
@@ -106,21 +106,20 @@ inline static int fixup_t_send_reply(void** param, int param_no);
106 106
 inline static int fixup_str2int( void** param, int param_no);
107 107
 inline static int w_t_retransmit_reply(struct sip_msg* p_msg, char* foo, char* bar );
108 108
 inline static int w_t_newtran(struct sip_msg* p_msg, char* foo, char* bar );
109
-inline static int w_t_newdlg( struct sip_msg* p_msg, char* foo, char* bar );
110 109
 inline static int w_t_relay( struct sip_msg  *p_msg , char *_foo, char *_bar);
111 110
 inline static int w_t_relay_to_udp( struct sip_msg  *p_msg , char *proxy, 
112
-									char *);
111
+				    char *);
113 112
 inline static int w_t_relay_to_tcp( struct sip_msg  *p_msg , char *proxy,
114
-									char *);
113
+				    char *);
115 114
 inline static int w_t_replicate( struct sip_msg  *p_msg , 
116
-							char *proxy, /* struct proxy_l *proxy expected */
117
-							char *_foo       /* nothing expected */ );
115
+				 char *proxy, /* struct proxy_l *proxy expected */
116
+				 char *_foo       /* nothing expected */ );
118 117
 inline static int w_t_replicate_udp( struct sip_msg  *p_msg , 
119
-							char *proxy, /* struct proxy_l *proxy expected */
120
-							char *_foo       /* nothing expected */ );
118
+				     char *proxy, /* struct proxy_l *proxy expected */
119
+				     char *_foo       /* nothing expected */ );
121 120
 inline static int w_t_replicate_tcp( struct sip_msg  *p_msg , 
122
-							char *proxy, /* struct proxy_l *proxy expected */
123
-							char *_foo       /* nothing expected */ );
121
+				     char *proxy, /* struct proxy_l *proxy expected */
122
+				     char *_foo       /* nothing expected */ );
124 123
 inline static int w_t_forward_nonack(struct sip_msg* msg, char* str, char* );
125 124
 inline static int w_t_forward_nonack_udp(struct sip_msg* msg, char* str,char*);
126 125
 inline static int w_t_forward_nonack_tcp(struct sip_msg* msg, char* str,char*);
... ...
@@ -157,14 +156,21 @@ static cmd_export_t cmds[]={
157 156
 			REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE },
158 157
 	/* not applicable from the script */
159 158
 	{"register_tmcb",      (cmd_function)register_tmcb,     NO_SCRIPT,     0, 0},
160
-	{T_UAC_DLG,            (cmd_function)t_uac_dlg,         NO_SCRIPT,     0, 0},
161 159
 	{"load_tm",            (cmd_function)load_tm,           NO_SCRIPT,     0, 0},
162 160
 	{T_REPLY_WB,           (cmd_function)t_reply_with_body, NO_SCRIPT,     0, 0},
163 161
 	{T_IS_LOCAL,           (cmd_function)t_is_local,        NO_SCRIPT,     0, 0},
164 162
 	{T_GET_TI,             (cmd_function)t_get_trans_ident, NO_SCRIPT,     0, 0},
165 163
 	{T_LOOKUP_IDENT,       (cmd_function)t_lookup_ident,    NO_SCRIPT,     0, 0},
166 164
 	{T_ADDBLIND,           (cmd_function)add_blind_uac,     NO_SCRIPT,     0, 0},
167
-	{"t_newdlg",           (cmd_function)w_t_newdlg,        0,             0, 0},
165
+	{"t_request_within",   (cmd_function)req_within,        NO_SCRIPT,     0, 0},
166
+	{"t_request_outside",  (cmd_function)req_outside,       NO_SCRIPT,     0, 0},
167
+	{"t_request",          (cmd_function)request,           NO_SCRIPT,     0, 0},
168
+	{"new_dlg_uac",        (cmd_function)new_dlg_uac,       NO_SCRIPT,     0, 0},
169
+	{"dlg_response_uac",   (cmd_function)dlg_response_uac,  NO_SCRIPT,     0, 0},
170
+	{"new_dlg_uas",        (cmd_function)new_dlg_uas,       NO_SCRIPT,     0, 0},
171
+	{"dlg_request_uas",    (cmd_function)dlg_request_uas,   NO_SCRIPT,     0, 0},
172
+	{"free_dlg",           (cmd_function)free_dlg,          NO_SCRIPT,     0, 0},
173
+	{"print_dlg",          (cmd_function)print_dlg,         NO_SCRIPT,     0, 0},
168 174
 	{0,0,0,0,0}
169 175
 };
170 176
 
... ...
@@ -179,6 +185,7 @@ static param_export_t params[]={
179 185
 	{"retr_timer1p3", INT_PARAM, &(timer_id2timeout[RT_T1_TO_3])        },
180 186
 	{"retr_timer2",   INT_PARAM, &(timer_id2timeout[RT_T2])             },
181 187
 	{"noisy_ctimer",  INT_PARAM, &noisy_ctimer                          },
188
+	{"uac_from",      STR_PARAM, &uac_from                              },
182 189
 	{0,0,0}
183 190
 };
184 191
 
... ...
@@ -261,11 +268,16 @@ static int mod_init(void)
261 268
 		return -1;
262 269
 	}
263 270
 
271
+	if (init_callid() < 0) {
272
+		LOG(L_CRIT, "Error while initializin Call-ID generator\n");
273
+		return -1;
274
+	}
264 275
 
265
-	if (register_fifo_cmd(fifo_uac_dlg, "t_uac_dlg", 0)<0) {
266
-		LOG(L_CRIT, "cannot register fifo uac\n");
276
+	if (register_fifo_cmd(fifo_uac, "t_uac_dlg", 0) < 0) {
277
+		LOG(L_CRIT, "cannot register fifo t_uac\n");
267 278
 		return -1;
268 279
 	}
280
+
269 281
 	if (register_fifo_cmd(fifo_hash, "t_hash", 0)<0) {
270 282
 		LOG(L_CRIT, "cannot register hash\n");
271 283
 		return -1;
... ...
@@ -317,11 +329,12 @@ static int mod_init(void)
317 329
 }
318 330
 
319 331
 static int child_init(int rank) {
320
-	if (uac_child_init(rank)==-1) {
321
-		LOG(L_ERR, "ERROR: child_init: uac_child_init error\n");
322
-		return -1;
332
+	if (child_init_callid(rank) < 0) {
333
+		LOG(L_ERR, "ERROR: child_init: Error while initializing Call-ID generator\n");
334
+		return -2;
323 335
 	}
324
-	return 1;
336
+
337
+	return 0;
325 338
 }
326 339
 
327 340
 
... ...
@@ -507,14 +520,6 @@ inline static int w_t_retransmit_reply( struct sip_msg* p_msg, char* foo, char*
507 520
 }
508 521
 
509 522
 
510
-
511
-
512
-
513
-inline static int w_t_newdlg( struct sip_msg* p_msg, char* foo, char* bar ) 
514
-{
515
-	return t_newdlg( p_msg );
516
-}
517
-
518 523
 inline static int w_t_newtran( struct sip_msg* p_msg, char* foo, char* bar ) 
519 524
 {
520 525
 	/* t_newtran returns 0 on error (negative value means
... ...
@@ -58,10 +58,6 @@ int load_tm( struct tm_binds *tmb)
58 58
 		LOG(L_ERR, LOAD_ERROR "'t_relay' not found\n");
59 59
 		return -1;
60 60
 	}
61
-	if (!(tmb->t_uac_dlg=(tuacdlg_f)find_export(T_UAC_DLG, NO_SCRIPT, 0)) ) {
62
-		LOG( L_ERR, LOAD_ERROR "'t_uac_dlg' not found\n");
63
-		return -1;
64
-	}
65 61
 	if (!(tmb->t_reply=(treply_f)find_export(T_REPLY, 2, 0)) ) {
66 62
 		LOG( L_ERR, LOAD_ERROR "'t_reply' not found\n");
67 63
 		return -1;
... ...
@@ -90,7 +86,42 @@ int load_tm( struct tm_binds *tmb)
90 86
 		LOG( L_ERR, LOAD_ERROR "'t_forward_nonack' not found\n");
91 87
 		return -1;
92 88
 	}
93
-
89
+	if (!(tmb->t_request_within=(reqwith_t)find_export("t_request_within", NO_SCRIPT, 0)) ) {
90
+		LOG( L_ERR, LOAD_ERROR "'t_request_within' not found\n");
91
+		return -1;
92
+	}
93
+	if (!(tmb->t_request_outside=(reqout_t)find_export("t_request_outside", NO_SCRIPT, 0)) ) {
94
+		LOG( L_ERR, LOAD_ERROR "'t_request_outside' not found\n");
95
+		return -1;
96
+	}
97
+	if (!(tmb->t_request=(req_t)find_export("t_request", NO_SCRIPT, 0)) ) {
98
+		LOG( L_ERR, LOAD_ERROR "'t_request' not found\n");
99
+		return -1;
100
+	}
101
+	if (!(tmb->new_dlg_uac=(new_dlg_uac_f)find_export("new_dlg_uac", NO_SCRIPT, 0)) ) {
102
+		LOG( L_ERR, LOAD_ERROR "'new_dlg_uac' not found\n");
103
+		return -1;
104
+	}
105
+        if (!(tmb->dlg_response_uac=(dlg_response_uac_f)find_export("dlg_response_uac", NO_SCRIPT, 0)) ) {
106
+		LOG( L_ERR, LOAD_ERROR "'dlg_response_uac' not found\n");
107
+		return -1;
108
+        }
109
+        if (!(tmb->new_dlg_uas=(new_dlg_uas_f)find_export("new_dlg_uas", NO_SCRIPT, 0)) ) {
110
+		LOG( L_ERR, LOAD_ERROR "'new_dlg_uas' not found\n");
111
+		return -1;
112
+	}
113
+        if (!(tmb->dlg_request_uas=(dlg_request_uas_f)find_export("dlg_request_uas", NO_SCRIPT, 0)) ) {
114
+		LOG( L_ERR, LOAD_ERROR "'dlg_request_uas' not found\n");
115
+		return -1;
116
+	}
117
+	if (!(tmb->free_dlg=(free_dlg_f)find_export("free_dlg", NO_SCRIPT, 0)) ) {
118
+		LOG( L_ERR, LOAD_ERROR "'free_dlg' not found\n");
119
+		return -1;
120
+	}
121
+	if (!(tmb->print_dlg=(print_dlg_f)find_export("print_dlg", NO_SCRIPT, 0)) ) {
122
+		LOG( L_ERR, LOAD_ERROR "'print_dlg' not found\n");
123
+		return -1;
124
+	}
125
+	
94 126
 	return 1;
95
-
96 127
 }
... ...
@@ -44,45 +44,55 @@
44 44
 #include "t_fwd.h"
45 45
 #include "t_reply.h"
46 46
 #include "t_lookup.h"
47
+#include "dlg.h"
47 48
 
48 49
 /* export not usable from scripts */
49 50
 #define NO_SCRIPT	-1
50 51
 
51
-#define T_RELAY_TO "t_relay_to"
52
-#define T_RELAY_TO_UDP "t_relay_to_udp"
53
-#define T_RELAY_TO_TCP "t_relay_to_tcp"
54
-#define T_RELAY "t_relay"
55
-#define T_RELAY_UDP "t_relay_udp"
56
-#define T_RELAY_TCP "t_relay_tcp"
57
-#define T_UAC_DLG "t_uac_dlg"
58
-#define T_REPLY "t_reply"
59
-#define T_REPLY_WB "t_reply_with_body"
60
-#define T_ADDBLIND "t_add_blind"
61
-#define T_REPLY_UNSAFE "t_reply_unsafe"
62
-#define T_FORWARD_NONACK "t_forward_nonack"
52
+#define T_RELAY_TO           "t_relay_to"
53
+#define T_RELAY_TO_UDP       "t_relay_to_udp"
54
+#define T_RELAY_TO_TCP       "t_relay_to_tcp"
55
+#define T_RELAY              "t_relay"
56
+#define T_RELAY_UDP          "t_relay_udp"
57
+#define T_RELAY_TCP          "t_relay_tcp"
58
+#define T_REPLY              "t_reply"
59
+#define T_REPLY_WB           "t_reply_with_body"
60
+#define T_ADDBLIND           "t_add_blind"
61
+#define T_REPLY_UNSAFE       "t_reply_unsafe"
62
+#define T_FORWARD_NONACK     "t_forward_nonack"
63 63
 #define T_FORWARD_NONACK_UDP "t_forward_nonack_udp"
64 64
 #define T_FORWARD_NONACK_TCP "t_forward_nonack_tcp"
65
-#define T_GET_TI       "t_get_trans_ident"
66
-#define T_LOOKUP_IDENT "t_lookup_ident"
67
-#define T_IS_LOCAL     "t_is_local"
68
-
65
+#define T_GET_TI             "t_get_trans_ident"
66
+#define T_LOOKUP_IDENT       "t_lookup_ident"
67
+#define T_IS_LOCAL           "t_is_local"
68
+#define T_REQUEST_WITHIN     "request_within"
69
+#define T_REQUEST_OUTSIDE    "request_outside"
69 70
 
70 71
 
71 72
 
72 73
 struct tm_binds {
73
-	register_tmcb_f	register_tmcb;
74
-	cmd_function	t_relay_to_udp;
75
-	cmd_function	t_relay_to_tcp;
76
-	cmd_function 	t_relay;
77
-	tuacdlg_f		t_uac_dlg;
78
-	treply_f		t_reply;
79
-	treply_wb_f		t_reply_with_body;
80
-	tislocal_f		t_is_local;
81
-	tget_ti_f		t_get_trans_ident;
74
+	register_tmcb_f register_tmcb;
75
+	cmd_function    t_relay_to_udp;
76
+	cmd_function    t_relay_to_tcp;
77
+	cmd_function    t_relay;
78
+	treply_f        t_reply;
79
+	treply_wb_f     t_reply_with_body;
80
+	tislocal_f      t_is_local;
81
+	tget_ti_f       t_get_trans_ident;
82 82
 	tlookup_ident_f t_lookup_ident;
83
-	taddblind_f		t_addblind;
84
-	treply_f		t_reply_unsafe;
85
-	tfwd_f			t_forward_nonack;
83
+	taddblind_f     t_addblind;
84
+	treply_f        t_reply_unsafe;
85
+	tfwd_f          t_forward_nonack;
86
+	reqwith_t       t_request_within;
87
+	reqout_t        t_request_outside;
88
+	req_t           t_request;
89
+	
90
+	new_dlg_uac_f      new_dlg_uac;
91
+	dlg_response_uac_f dlg_response_uac;
92
+	new_dlg_uas_f      new_dlg_uas;
93
+	dlg_request_uas_f  dlg_request_uas;
94
+	free_dlg_f         free_dlg;
95
+	print_dlg_f        print_dlg;
86 96
 };
87 97
 
88 98
 
... ...
@@ -30,18 +30,6 @@
30 30
  * along with this program; if not, write to the Free Software 
31 31
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
32 32
  *
33
- * ***************************************************
34
- *             IMPORTANT NOTE
35
- *
36
- *    All UACs but t_uac_dlg are being deprecated now
37
- *    and will be removed from future versions of TM
38
- *    module. Eliminate all dependancies on them asap.
39
- *    For backwards compatibility (NOT RECOMMENDED)
40
- *    turn off DEPRECATE_OLD_STUFF in defs.h. Similarly,
41
- *    there is a new FIFO UAC.
42
- *
43
- * ****************************************************
44
- *
45 33
  * History:
46 34
  * --------
47 35
  *  2003-01-23  t_uac_dlg now uses get_out_socket (jiri)
... ...
@@ -54,816 +42,260 @@
54 42
  *  2003-03-01  kr set through a function now (jiri)
55 43
  *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
56 44
  *  2003-04-02  port_no_str does not contain a leading ':' anymore (andrei)
57
- *  2003-04-15  t_uac_dlg now uses get_send_socket(get_out_socket doesn't
58
- *               work for tcp) (andrei)
59
- *  
60 45
  */
61 46
 
62
-
63
-#include "../../comp_defs.h"
64
-#include "defs.h"
65
-
66
-
67
-#include <stdlib.h>
68
-#include <sys/types.h>
69
-#include <unistd.h>
70
-#include <stdio.h>
71
-#include <errno.h>
72
-#include <sys/types.h>
73
-#include <sys/stat.h>
74
-#include <fcntl.h>
75
-#include <signal.h>
76
-#include <limits.h>
77 47
 #include <string.h>
78
-#include "../../parser/parse_from.h"
79
-#include "../../parser/msg_parser.h"
48
+#include "../../mem/shm_mem.h"
80 49
 #include "../../dprint.h"
81
-#include "../../ut.h"
82
-#include "../../hash_func.h"
83
-#include "../../md5utils.h"
84
-#include "../../mem/mem.h"
85
-#include "../../fifo_server.h"
86
-#include "../../error.h"
87
-#include "../../pt.h"
50
+#include "../../globals.h"
51
+#include "../../md5.h"
88 52
 #include "../../crc.h"
89
-#include "t_funcs.h"
90
-#include "config.h"
91
-#include "sip_msg.h"
53
+#include "../../ip_addr.h"
92 54
 #include "ut.h"
55
+#include "h_table.h"
56
+#include "t_hooks.h"
57
+#include "t_funcs.h"
93 58
 #include "t_msgbuilder.h"
59
+#include "callid.h"
94 60
 #include "uac.h"
95 61
 
96
-/* header fields which are explicitely processed and are not copied
97
- * from FIFO line-by-line
98
- */
99
-#define skip_hf(_hf) (((_hf)->type==HDR_FROM) || ((_hf)->type==HDR_TO) \
100
-	|| ((_hf)->type==HDR_CALLID) || ((_hf)->type==HDR_CSEQ))
101
-
102
-/* Call-ID has the following form: <callid_nr>-<pid>@<ip>
103
- * callid_nr is initialized as a random number and continually
104
- * increases; -<pid>@<ip> is kept in callid_suffix
105
- */
106
-
107
-#define CALLID_SUFFIX_LEN (1 /* - */ + 5 /* pid */ \
108
-	+ 42 /* embedded v4inv6 address can be looong '128.' */ \
109
-	+ 2 /* parenthessis [] */ + 1 /* ZT 0 */ \
110
-	+ 16 /* one never knows ;-) */ )
111
-#define CALLID_NR_LEN 20
112
-
113
-/* the character which separates random from constant part */
114
-#define CID_SEP	'-'
115
-
116
-/* length of FROM tags */
117
-#define FROM_TAG_LEN (MD5_LEN +1 /* - */ + CRC16_LEN)
118
-
119
-struct str_list {
120
-	str s;
121
-	struct str_list *next;
122
-};
123 62
 
124
-static unsigned long callid_nr;
125
-static char *callid_suffix;
126
-static int callid_suffix_len;
127
-static int rand_len;	/* number of chars to display max rand */
128
-static char callid[CALLID_NR_LEN+CALLID_SUFFIX_LEN];
63
+#define FROM_TAG_LEN (MD5_LEN + 1 /* - */ + CRC16_LEN) /* length of FROM tags */
129 64
 
130
-static char from_tag[ FROM_TAG_LEN+1 ];
65
+static char from_tag[FROM_TAG_LEN + 1];
131 66
 
67
+char* uac_from = "sip:foo@foo.bar"; /* Module parameter */
132 68
 
133 69
 
134
-int uac_init() {
135
-
136
-	int i; 
137
-	unsigned long uli;
138
-	int rand_len_bits;
139
-	int rand_cnt; /* number of rands() to be long enough */
140
-	int rand_bits; /* length of rands() in bits */
70
+/*
71
+ * Initialize UAC
72
+ */
73
+int uac_init(void) 
74
+{
141 75
 	str src[3];
142 76
 
143
-	if (RAND_MAX<TABLE_ENTRIES) {
77
+	if (RAND_MAX < TABLE_ENTRIES) {
144 78
 		LOG(L_WARN, "Warning: uac does not spread "
145
-			"accross the whole hash table\n");
146
-	}
147
-
148
-	/* calculate the initial call-id */
149
-
150
-	/* how many bits and chars do we need to display the 
151
-	 * whole ULONG number */
152
-	for (rand_len_bits=0,uli=ULONG_MAX;uli;
153
-			uli>>=1, rand_len_bits++ );
154
-	rand_len=rand_len_bits/4;
155
-	if (rand_len>CALLID_NR_LEN) {
156
-		LOG(L_ERR, "ERROR: Too small callid buffer\n");
157
-		return -1;
158
-	}
159
-
160
-	/* how long are the rand()s ? */
161
-	for (rand_bits=0,i=RAND_MAX;i;i>>=1,rand_bits++);
162
-	/* how many rands() fit in the ULONG ? */
163
-	rand_cnt=rand_len_bits / rand_bits;
164
-
165
-	/* now fill in the callid with as many random
166
-	 * numbers as you can + 1 */
167
-	callid_nr=rand(); /* this is the + 1 */
168
-	while(rand_cnt) {
169
-		rand_cnt--;
170
-		callid_nr<<=rand_bits;
171
-		callid_nr|=rand();
79
+		    "accross the whole hash table\n");
172 80
 	}
173
-	callid_suffix=callid+rand_len;
174
-	DBG("CALLID initialization: %lx (len=%d)\n", 
175
-			callid_nr, rand_len );
176
-	DBG("CALLID0=%0*lx\n", rand_len, callid_nr );
177
-
178 81
 
179 82
 	/* calculate the initial From tag */
180
-
181
-	src[0].s="Long live SER server";
182
-	src[0].len=strlen(src[0].s);
183
-	src[1].s=sock_info[bind_idx].address_str.s;
184
-	src[1].len=strlen(src[1].s);
185
-	src[2].s=sock_info[bind_idx].port_no_str.s;
186
-	src[2].len=strlen(src[2].s);
187
-
188
-	MDStringArray( from_tag, src, 3 );
189
-	from_tag[MD5_LEN]=CID_SEP;
190
-
83
+	src[0].s = "Long live SER server";
84
+	src[0].len = strlen(src[0].s);
85
+	src[1].s = sock_info[bind_idx].address_str.s;
86
+	src[1].len = strlen(src[1].s);
87
+	src[2].s = sock_info[bind_idx].port_no_str.s;
88
+	src[2].len = strlen(src[2].s);
89
+
90
+	MDStringArray(from_tag, src, 3);
91
+	from_tag[MD5_LEN] = '-';
191 92
 	return 1;
192 93
 }
193 94
 
194 95
 
195
-int uac_child_init( int rank ) 
96
+/*
97
+ * Generate a From tag
98
+ */
99
+void generate_fromtag(str* tag, str* callid)
196 100
 {
197
-	callid_suffix_len=snprintf(callid_suffix,CALLID_SUFFIX_LEN,
198
-			"%c%d@%.*s", CID_SEP, my_pid(), 
199
-			sock_info[bind_idx].address_str.len,
200
-			sock_info[bind_idx].address_str.s );
201
-	if (callid_suffix_len==-1 || callid_suffix_len>=CALLID_SUFFIX_LEN) {
202
-		LOG(L_ERR, "ERROR: uac_child_init: buffer too small\n");
203
-		return -1;
204
-	}
205
-	DBG("DEBUG: callid_suffix: %s\n", callid_suffix );
206
-	return 1;
101
+	     /* calculate from tag from callid */
102
+	crcitt_string_array(&from_tag[MD5_LEN + 1], callid, 1);
103
+	tag->s = from_tag; 
104
+	tag->len = FROM_TAG_LEN;
207 105
 }
208 106
 
209
-static struct socket_info *uri2sock( str *uri, union sockaddr_union *to_su,
210
-									 int proto )
211
-{
212
-	struct proxy_l *proxy;
213
-	struct socket_info* send_sock;
214 107
 
215
-	proxy = uri2proxy(uri, proto);
216
-	if (proxy == 0) {
217
-		ser_error = E_BAD_ADDRESS;
218
-		LOG(L_ERR, "ERROR: uri2sock: Can't create a dst proxy\n");
219
-		return 0;
108
+/*
109
+ * Check value of parameters
110
+ */
111
+static inline int check_params(str* method, str* to, str* from, dlg_t** dialog)
112
+{
113
+	if (!method || !to || !from || !dialog) {
114
+		LOG(L_ERR, "check_params(): Invalid parameter value\n");
115
+		return -1;
220 116
 	}
221 117
 
222
-	hostent2su(to_su, &proxy->host, proxy->addr_idx, 
223
-			(proxy->port) ? proxy->port : SIP_PORT);
224
-	send_sock=get_send_socket(to_su, proxy->proto);
225
-	if (send_sock == 0) {
226
-		LOG(L_ERR, "ERROR: uri2sock: no corresponding socket for af %d,"
227
-				"proto %d\n", to_su->s.sa_family , proto);
228
-		ser_error = E_NO_SOCKET;
118
+	if (!method->s || !method->len) {
119
+		LOG(L_ERR, "check_params(): Invalid request method\n");
120
+		return -2;
229 121
 	}
230 122
 
123
+	if (!to->s || !to->len) {
124
+		LOG(L_ERR, "check_params(): Invalid request method\n");
125
+		return -4;
126
+	}
231 127
 
232
-	free_proxy(proxy);
233
-	pkg_free(proxy);
234
-	return send_sock;
128
+	if (!from->s || !from->len) {
129
+		LOG(L_ERR, "check_params(): Invalid request method\n");
130
+		return -5;
131
+	}
132
+	return 0;
235 133
 }
236
-	
237 134
 
238 135
 
239 136
 /*
240
- * Send a request within a dialog
241
- * 
242
- * Some parameters are required, some are optional (i.e., ephemeral,
243
- * default or empty values are created if 0 is passed as parameter). The
244
- * optional parameters are typically used to set some header fields
245
- * to dialog-related values (as opposed to having them set to
246
- * ephemeral values).
247
- *
248
- * Required:
249
- * - msg ..   specifies type of message, such as "OPTIONS"
250
- * - ruri ..  specifies request URI; 
251
- * - from ..  value of From header field (if it already includes from tag, 
252
- *            the fromtag parameter MUST point to en empty string; if 
253
- *            fromtag is 0, an ephemeral tag is always appended)
254
- * - to ...   value of To header field (if it already includes to tag in it,
255
- *            or you do not wish to set a to-tag the totag parameter MUST be 0)
256
- * 
257
- * Optional:
258
- * - dst     transport destination (expressed as URI) -- if present,
259
- *           request is physically forwarded to address indicated in it,
260
- *           overriding the transport address in ruri; useful for use with 
261
- *           outbound proxies or loose routers (that is where the first 
262
- *           element of route set comes in)
263
- * - fromtag from HF tag -- dialog-less applications do not to set it (==0),
264
- *           in which case an ephemeral value is created; if fromtag present,
265
- *           its appended to the From header field; it may be also present 
266
- *           and point to an empty string -- that only makes sense if
267
- *           application includes the tag in From and does not care to
268
- *           separate the tag from the rest of header field
269
- * - totag   To HF tag; if 0, no to-tag is appended (unless it is already
270
- *           part of to)
271
- * - cid ..  callid; if 0, ephemeral value is created; transactions
272
- *           within a dialog need to set this value to dialog's callid
273
- * - cseq .. CSeq; if 0, default value (DEFAULT_CSEQ) is used; transactions
274
- *           within a dialog need to set this value to current local cseq,
275
- *           which grows continously with transactions sent
276
- * - headers .. block of header fields that will be included in the
277
- *           message. It MAY NOT include header fields already described
278
- *           in other parameters (From, to, cid, cseq) or created 
279
- *           automatically   (Content_length)   otherwise the parameter
280
- *           would appear multiple times. It MUST include all additional
281
- *           header fields required for a given SIP message, like Content-Type 
282
- *           for any messages including a body or Contact for INVITEs.
283
- * - body .. if present, body and Content-Length is appended to the 
284
- *           SIP message; Content-Type then needs to be present inside
285
- *           'headers' parameter
286
- * - cb ..   callback to be called when transaction completes; if none
287
- *           present, no callback will be called
288
- * - cbp ..  callback parameter -- value stored in transaction context
289
- *           
290
- *
137
+ * Send a request using data from the dialog structure
291 138
  */
292
-int t_uac_dlg(str* msg,                     /* Type of the message - MESSAGE, OPTIONS etc. */
293
-	      str* dst,                     /* Real destination (can be different than R-URI) */
294
-		  int proto,
295
-	      str* ruri,                    /* Request-URI */
296
-	      str* to,                      /* To - w/o tag*/
297
-	      str* from,                    /* From - w/o tag*/
298
-	      str* totag,                   /* To tag */
299
-	      str* fromtag,                 /* From tag */
300
-	      int* cseq,                    /* Variable holding CSeq */
301
-	      str* cid,                     /* Call-ID */
302
-	      str* headers,                 /* Optional headers including CRLF */
303
-	      str* body,                    /* Message body */
304
-	      transaction_cb completion_cb, /* Callback parameter */
305
-	      void* cbp                     /* Callback pointer */
306
-	      )
139
+int t_uac(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb cb, void* cbp)
307 140
 {
308
-
309
-	int r, branch, ret;
310
-	unsigned int req_len;
311
-	char *buf;
312
-	struct cell *new_cell;
313 141
 	struct socket_info* send_sock;
314
-	struct retr_buf *request;
315
-	str callid_s, ftag, tmp;
316 142
 	union sockaddr_union to_su;
143
+	struct cell *new_cell;
144
+	struct retr_buf *request;
145
+	char* buf;
146
+	int buf_len;
317 147
 
318
-	/* make -Wall shut up */
319
-	ret=0;
320
-
321
-	/* check for invalid parameter */
322
-	if (!msg || !msg->s
323
-				|| !ruri || !ruri->s
324
-				|| !from || !from->s
325
-				|| !to || !to->s ) {
326
-		LOG(L_ERR, "ERROR: t_uac_dlg: invalid parameters\n");
327
-		ser_error = ret = E_INVALID_PARAMS;
328
-#ifdef XL_DEBUG
329
-		abort();
330
-#endif
331
-		goto done;
332
-	}
333
-
334
-	send_sock=uri2sock( dst? dst: ruri, &to_su, proto );
335
-	if (send_sock==0) {
336
-		LOG(L_ERR, "ERROR: t_uac_dlg: no socket found\n");
337
-		goto error00;
338
-	}
339
-
340
-	branch=0;
341
-	     /* No Call-ID given, calculate it */
342
-	if (cid == 0) {
343
-		callid_nr++;
344
-		r = snprintf(callid, rand_len + 1, "%0*lx", rand_len, callid_nr);
345
-		if (r == -1 || r>=rand_len+1) {
346
-			LOG(L_CRIT, "BUG: SORRY, callid calculation failed\n");
347
-			goto error00;
348
-		}
349
-
350
-		     /* fix the ZT 0 */
351
-		callid[rand_len] = CID_SEP;
352
-		callid_s.s = callid;
353
-		callid_s.len = rand_len + callid_suffix_len;
354
-	}
148
+	send_sock = uri2sock(dialog->hooks.next_hop, &to_su, PROTO_NONE);
149
+	if (!send_sock) {
150
+		LOG(L_ERR, "t_uac: no socket found\n");
151
+		goto error2;
152
+	}	
355 153
 
356 154
 	new_cell = build_cell(0); 
357 155
 	if (!new_cell) {
358
-		ret = E_OUT_OF_MEM;
359
-		LOG(L_ERR, "ERROR: t_uac: short of cell shmem\n");
360
-		goto error00;
156
+		LOG(L_ERR, "t_uac: short of cell shmem\n");
157
+		goto error2;
361 158
 	}
362 159
 
363
-	new_cell->completion_cb = completion_cb;
160
+	new_cell->completion_cb = cb;
364