Browse code

- force_send_socket per message API support => changedinterface to get_send_socket; it takes now also the sip msg as param (updated the calls to it in all the modules)

Andrei Pelinescu-Onciul authored on 09/11/2004 15:15:11
Showing 17 changed files
... ...
@@ -50,7 +50,7 @@ MAIN_NAME=ser
50 50
 VERSION = 0
51 51
 PATCHLEVEL = 8
52 52
 SUBLEVEL =   99
53
-EXTRAVERSION = -dev12
53
+EXTRAVERSION = -dev13
54 54
 
55 55
 RELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
56 56
 OS = $(shell uname -s | sed -e s/SunOS/solaris/ | tr "[A-Z]" "[a-z]")
... ...
@@ -241,7 +241,7 @@ int do_action(struct action* a, struct sip_msg* msg)
241 241
 				p->tx_bytes+=msg->len;
242 242
 				if (a->type==SEND_T){
243 243
 					/*udp*/
244
-					send_sock=get_send_socket(to, PROTO_UDP);
244
+					send_sock=get_send_socket(msg, to, PROTO_UDP);
245 245
 					if (send_sock!=0){
246 246
 						ret=udp_send(send_sock, msg->buf, msg->len, to);
247 247
 					}else{
... ...
@@ -45,6 +45,7 @@
45 45
  *  2003-10-21  check_self updated to handle proto (andrei)
46 46
  *  2003-10-24  converted to the new socket_info lists (andrei)
47 47
  *  2004-10-10  modified check_self to use grep_sock_info (andrei)
48
+ *  2004-11-08  added force_send_socket support in get_send_socket (andrei)
48 49
  */
49 50
 
50 51
 
... ...
@@ -79,6 +80,8 @@
79 79
 #include <dmalloc.h>
80 80
 #endif
81 81
 
82
+
83
+
82 84
 /* return a socket_info_pointer to the sending socket; as opposed to
83 85
  * get_send_socket, which returns process's default socket, get_out_socket
84 86
  * attempts to determine the outbound interface which will be used;
... ...
@@ -153,11 +156,29 @@ found:
153 153
 
154 154
 
155 155
 /* returns a socket_info pointer to the sending socket or 0 on error
156
- * params: destination socket_union pointer
156
+ * params: sip msg (can be null), destination socket_union pointer, protocol
157
+ * if msg!=null and msg->force_send_socket, the force_send_socket will be
158
+ * used
157 159
  */
158
-struct socket_info* get_send_socket(union sockaddr_union* to, int proto)
160
+struct socket_info* get_send_socket(struct sip_msg *msg, 
161
+										union sockaddr_union* to, int proto)
159 162
 {
160 163
 	struct socket_info* send_sock;
164
+	
165
+	/* check if send interface is not forced */
166
+	if (msg && msg->force_send_socket){
167
+		if (msg->force_send_socket->proto!=proto){
168
+			DBG("get_send_socket: force_send_socket of different proto"
169
+					" (%d)!\n", proto);
170
+			msg->force_send_socket=find_si(&(msg->force_send_socket->address),
171
+											msg->force_send_socket->port_no,
172
+											proto);
173
+		}
174
+		if (msg->force_send_socket) 
175
+			return msg->force_send_socket;
176
+		else
177
+			LOG(L_WARN, "WARNING: get_send_socket: protocol/port mismatch\n");
178
+	};
161 179
 
162 180
 	if (mhomed && proto==PROTO_UDP) return get_out_socket(to, proto);
163 181
 
... ...
@@ -278,7 +299,7 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p, int proto)
278 278
 	p->tx_bytes+=len;
279 279
 	
280 280
 
281
-	send_sock=get_send_socket(to, proto);
281
+	send_sock=get_send_socket(msg, to, proto);
282 282
 	if (send_sock==0){
283 283
 		LOG(L_ERR, "forward_req: ERROR: cannot forward to af %d, proto %d "
284 284
 				"no corresponding listening socket\n", to->s.sa_family, proto);
... ...
@@ -53,7 +53,9 @@
53 53
 #endif
54 54
 
55 55
 
56
-struct socket_info* get_send_socket(union sockaddr_union* su, int proto);
56
+
57
+struct socket_info* get_send_socket(struct sip_msg* msg,
58
+									union sockaddr_union* su, int proto);
57 59
 struct socket_info* get_out_socket(union sockaddr_union* to, int proto);
58 60
 int check_self(str* host, unsigned short port, unsigned short proto);
59 61
 int forward_request( struct sip_msg* msg,  struct proxy_l* p, int proto);
... ...
@@ -87,7 +89,7 @@ static inline int msg_send(	struct socket_info* send_sock, int proto,
87 87
 {
88 88
 	
89 89
 	if (proto==PROTO_UDP){
90
-		if (send_sock==0) send_sock=get_send_socket(to, proto);
90
+		if (send_sock==0) send_sock=get_send_socket(0, to, proto);
91 91
 		if (send_sock==0){
92 92
 			LOG(L_ERR, "msg_send: ERROR: no sending socket found\n");
93 93
 			goto error;
... ...
@@ -215,7 +215,7 @@ int add_uac( struct cell *t, struct sip_msg *request, str *uri, str* next_hop,
215 215
 	hostent2su( &to, &proxy->host, proxy->addr_idx, 
216 216
 		proxy->port ? proxy->port:SIP_PORT);
217 217
 
218
-	send_sock=get_send_socket( &to , proto);
218
+	send_sock=get_send_socket( request, &to , proto);
219 219
 	if (send_sock==0) {
220 220
 		LOG(L_ERR, "ERROR: add_uac: can't fwd to af %d, proto %d "
221 221
 			" (no corresponding listening socket)\n",
... ...
@@ -933,7 +933,7 @@ int init_rb( struct retr_buf *rb, struct sip_msg *msg)
933 933
 	*/
934 934
 	backup_mhomed=mhomed;
935 935
 	mhomed=0;
936
-	send_sock=get_send_socket(&rb->dst.to, proto);
936
+	send_sock=get_send_socket(msg, &rb->dst.to, proto);
937 937
 	mhomed=backup_mhomed;
938 938
 	if (send_sock==0) {
939 939
 		LOG(L_ERR, "ERROR: init_rb: cannot fwd to af %d, proto %d "
... ...
@@ -408,7 +408,7 @@ char *build_dlg_ack(struct sip_msg* rpl, struct cell *Trans, unsigned int branch
408 408
 	
409 409
 	
410 410
 	     /* via */
411
-	send_sock = uri2sock(next_hop, &to_su, PROTO_NONE);
411
+	send_sock = uri2sock(rpl, next_hop, &to_su, PROTO_NONE);
412 412
 	if (!send_sock) {
413 413
 		LOG(L_ERR, "build_dlg_ack: no socket found\n");
414 414
 		goto error;
... ...
@@ -309,7 +309,8 @@ static char *build_local_ack(struct sip_msg* rpl, struct cell *trans, int branch
309 309
       * The function is used to send a localy generated ACK to INVITE
310 310
       * (tm generates the ACK on behalf of application using UAC
311 311
       */
312
-static int send_local_ack(str* next_hop, char* ack, int ack_len)
312
+static int send_local_ack(struct sip_msg* msg, str* next_hop,
313
+							char* ack, int ack_len)
313 314
 {
314 315
 	struct socket_info* send_sock;
315 316
 	union sockaddr_union to_su;
... ...
@@ -319,7 +320,7 @@ static int send_local_ack(str* next_hop, char* ack, int ack_len)
319 319
 		return -1;
320 320
 	}
321 321
 	
322
-	send_sock = uri2sock(next_hop, &to_su, PROTO_NONE);
322
+	send_sock = uri2sock(msg, next_hop, &to_su, PROTO_NONE);
323 323
 	if (!send_sock) {
324 324
 		LOG(L_ERR, "send_local_ack: no socket found\n");
325 325
 		return -1;
... ...
@@ -480,6 +481,7 @@ static inline void faked_env( struct cell *t,struct sip_msg *msg)
480 480
 	static struct cell *backup_t;
481 481
 	static unsigned int backup_msgid;
482 482
 	static struct usr_avp **backup_list;
483
+	static struct socket_info* backup_si;
483 484
 
484 485
 	if (msg) {
485 486
 		/* remember we are back in request processing, but process
... ...
@@ -502,6 +504,9 @@ static inline void faked_env( struct cell *t,struct sip_msg *msg)
502 502
 		set_t(t);
503 503
 		/* make available the avp list from transaction */
504 504
 		backup_list = set_avp_list( &t->user_avps );
505
+		/* set default send address to the saved value */
506
+		backup_si=bind_address;
507
+		bind_address=t->uac[0].request.dst.send_sock;
505 508
 	} else {
506 509
 		/* restore original environment */
507 510
 		set_t(backup_t);
... ...
@@ -509,6 +514,7 @@ static inline void faked_env( struct cell *t,struct sip_msg *msg)
509 509
 		rmode=backup_mode;
510 510
 		/* restore original avp list */
511 511
 		set_avp_list( backup_list );
512
+		bind_address=backup_si;
512 513
 	}
513 514
 }
514 515
 
... ...
@@ -1255,7 +1261,7 @@ int reply_received( struct sip_msg  *p_msg )
1255 1255
 		} else if ((t->flags & T_IS_LOCAL_FLAG) && msg_status >= 200) {
1256 1256
 			ack = build_local_ack(p_msg, t, branch, &ack_len, &next_hop);
1257 1257
 			if (ack) {
1258
-				if (send_local_ack(&next_hop, ack, ack_len) < 0) {
1258
+				if (send_local_ack(p_msg, &next_hop, ack, ack_len) < 0) {
1259 1259
 					LOG(L_ERR, "Error while sending local ACK\n");
1260 1260
 				}
1261 1261
 				shm_free(ack);
... ...
@@ -185,7 +185,8 @@ int t_uac(str* method, str* headers, str* body, dlg_t* dialog,
185 185
 
186 186
 	DBG("DEBUG:tm:t_uac: next_hop=<%.*s>\n",dialog->hooks.next_hop->len,
187 187
 			dialog->hooks.next_hop->s);
188
-	send_sock = uri2sock(dialog->hooks.next_hop, &to_su, PROTO_NONE);
188
+	/* it's a new message, so we will take the default socket */
189
+	send_sock = uri2sock(0, dialog->hooks.next_hop, &to_su, PROTO_NONE);
189 190
 	if (!send_sock) {
190 191
 		ret=ser_error;
191 192
 		LOG(L_ERR, "t_uac: no socket found\n");
... ...
@@ -267,7 +267,7 @@ static char *get_hfblock(str *uri, struct hdr_field *hf, int *l, int proto)
267 267
 						if (!new) goto error;
268 268
 						/* substitute */
269 269
 						if (!sock_name) {
270
-							send_sock=uri2sock( uri, &to_su, proto );
270
+							send_sock=uri2sock(0, uri, &to_su, proto );
271 271
 							if (!send_sock) {
272 272
 								LOG(L_ERR, "ERROR: get_hfblock: send_sock failed\n");
273 273
 								goto error;
... ...
@@ -294,7 +294,7 @@ static char *get_hfblock(str *uri, struct hdr_field *hf, int *l, int proto)
294 294
 					if (!new_str(begin, frag_len, &last, &total_len)) goto error;
295 295
 					     /* substitute */
296 296
 					if (!sock_name) {
297
-						send_sock = uri2sock(uri, &to_su, proto);
297
+						send_sock = uri2sock(0, uri, &to_su, proto);
298 298
 						if (!send_sock) {
299 299
 							LOG(L_ERR, "ERROR: get_hfblock: send_sock failed\n");
300 300
 							goto error;
... ...
@@ -133,7 +133,8 @@ inline static struct proxy_l *uri2proxy( str *uri, int proto )
133 133
 /*
134 134
  * Convert a URI into socket_info
135 135
  */
136
-static inline struct socket_info *uri2sock(str *uri, union sockaddr_union *to_su, int proto)
136
+static inline struct socket_info *uri2sock(struct sip_msg* msg, str *uri,
137
+									union sockaddr_union *to_su, int proto)
137 138
 {
138 139
 	struct proxy_l *proxy;
139 140
 	struct socket_info* send_sock;
... ...
@@ -148,7 +149,7 @@ static inline struct socket_info *uri2sock(str *uri, union sockaddr_union *to_su
148 148
 	hostent2su(to_su, &proxy->host, proxy->addr_idx, 
149 149
 		   (proxy->port) ? proxy->port : SIP_PORT);
150 150
 			/* we use proxy->proto since uri2proxy just set it correctly*/
151
-	send_sock = get_send_socket(to_su, proxy->proto);
151
+	send_sock = get_send_socket(msg, to_su, proxy->proto);
152 152
 	if (!send_sock) {
153 153
 		LOG(L_ERR, "ERROR: uri2sock: no corresponding socket for af %d\n", 
154 154
 		    to_su->s.sa_family);
... ...
@@ -91,7 +91,7 @@ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
91 91
 	}
92 92
 
93 93
 	/* eliminate leading whitespace */
94
-	tmp=eat_lws_end(tmp, end);
94
+	/* tmp=eat_lws_end(tmp, end); not allowed anyway --andrei */
95 95
 	if (tmp>=end) {
96 96
 		LOG(L_ERR, "ERROR: get_hdr_field: HF empty\n");
97 97
 		goto error;
... ...
@@ -36,6 +36,7 @@
36 36
  *  2003-04-11  updated the  sip_uri structure (lots of fields added) (andrei)
37 37
  *  2003-04-12  added msg_flags to sip_msg (andrei)
38 38
  *  2003-11-02  added diversion header field to sip_msg (jh)
39
+ *  2004-11-08  added force_send_socket (andrei)
39 40
  */
40 41
 
41 42
 
... ...
@@ -237,6 +238,8 @@ struct sip_msg {
237 237
 	flag_t flags;	
238 238
 	str set_global_address;
239 239
 	str set_global_port;
240
+	struct socket_info* force_send_socket; /* force sending on this socket,
241
+											  if ser */
240 242
 };
241 243
 
242 244
 /* pointer to a fakes message which was never received ;
... ...
@@ -33,6 +33,7 @@
33 33
  * --------
34 34
  *  2003-10-22  created by andrei
35 35
  *  2004-10-10  added grep_sock_info (andrei)
36
+ *  2004-11-08  added find_si (andrei)
36 37
  */
37 38
 
38 39
 
... ...
@@ -205,7 +206,6 @@ struct socket_info* grep_sock_info(str* host, unsigned short port,
205 205
 #ifdef USE_IPV6
206 206
 	struct ip_addr* ip6;
207 207
 #endif
208
-
209 208
 	h_len=host->len;
210 209
 	hname=host->s;
211 210
 #ifdef USE_IPV6
... ...
@@ -279,6 +279,53 @@ found:
279 279
 
280 280
 
281 281
 
282
+/* checks if the proto: ip:port is one of the address we listen on
283
+ * and returns the corresponding socket_info structure.
284
+ * (same as grep_socket_info, but use ip addr instead)
285
+ * if port==0, the  port number is ignored
286
+ * if proto==0 (PROTO_NONE) the protocol is ignored
287
+ * returns  0 if not found
288
+ * WARNING: uses str2ip6 so it will overwrite any previous
289
+ *  unsaved result of this function (static buffer)
290
+ */
291
+struct socket_info* find_si(struct ip_addr* ip, unsigned short port,
292
+												unsigned short proto)
293
+{
294
+	struct socket_info* si;
295
+	struct socket_info** list;
296
+	unsigned short c_proto;
297
+	
298
+	c_proto=proto?proto:PROTO_UDP;
299
+	do{
300
+		/* get the proper sock_list */
301
+		if (c_proto==PROTO_NONE)
302
+			list=&udp_listen;
303
+		else
304
+			list=get_sock_info_list(c_proto);
305
+	
306
+		if (list==0){
307
+			LOG(L_WARN, "WARNING: grep_sock_info: "
308
+						"unknown proto %d\n", c_proto);
309
+			goto not_found; /* false */
310
+		}
311
+		for (si=*list; si; si=si->next){
312
+			if (port) {
313
+				if (si->port_no!=port) {
314
+					continue;
315
+				}
316
+			}
317
+			if (ip_addr_cmp(ip, &si->address))
318
+				goto found;
319
+		}
320
+	}while( (proto==0) && (c_proto=next_proto(c_proto)) );
321
+not_found:
322
+	return 0;
323
+found:
324
+	return si;
325
+}
326
+
327
+
328
+
282 329
 /* adds a new sock_info structure to the corresponding list
283 330
  * return  0 on success, -1 on error */
284 331
 int new_sock2list(char* name, unsigned short port, unsigned short proto,
... ...
@@ -59,6 +59,8 @@ void print_aliases();
59 59
 
60 60
 struct socket_info* grep_sock_info(str* host, unsigned short port,
61 61
 										unsigned short proto);
62
+struct socket_info* find_si(struct ip_addr* ip, unsigned short port,
63
+												unsigned short proto);
62 64
 
63 65
 /* helper function:
64 66
  * returns next protocol, if the last one is reached return 0
... ...
@@ -51,6 +51,7 @@
51 51
  *  2003-11-17  handle_new_connect & tcp_connect will close the 
52 52
  *              new socket if tcpconn_new return 0 (e.g. out of mem) (andrei)
53 53
  *  2003-11-28  tcp_blocking_write & tcp_blocking_connect added (andrei)
54
+ *  2004-11-08  dropped find_tcp_si and replaced with find_si (andrei)
54 55
  */
55 56
 
56 57
 
... ...
@@ -368,22 +369,6 @@ error:
368 368
 
369 369
 
370 370
 
371
-
372
-struct socket_info* find_tcp_si(union sockaddr_union* s)
373
-{
374
-	struct ip_addr ip;
375
-	struct socket_info* si;
376
-	
377
-	su2ip_addr(&ip, s);
378
-	for (si=tcp_listen; si; si=si->next)
379
-		if (ip_addr_cmp(&ip, &si->address)){
380
-			/* found it, we use first match */
381
-			return si;
382
-		}
383
-	return 0; /* no match */
384
-}
385
-
386
-
387 371
 struct tcp_connection* tcpconn_connect(union sockaddr_union* server, int type)
388 372
 {
389 373
 	int s;
... ...
@@ -391,6 +376,7 @@ struct tcp_connection* tcpconn_connect(union sockaddr_union* server, int type)
391 391
 	union sockaddr_union my_name;
392 392
 	socklen_t my_name_len;
393 393
 	struct tcp_connection* con;
394
+	struct ip_addr ip;
394 395
 
395 396
 	s=socket(AF2PF(server->s.sa_family), SOCK_STREAM, 0);
396 397
 	if (s==-1){
... ...
@@ -412,12 +398,13 @@ struct tcp_connection* tcpconn_connect(union sockaddr_union* server, int type)
412 412
 				strerror(errno), errno);
413 413
 		si=0; /* try to go on */
414 414
 	}
415
+	su2ip_addr(&ip, &my_name);
415 416
 #ifdef USE_TLS
416 417
 	if (type==PROTO_TLS)
417
-		si=find_tls_si(&my_name);
418
+		si=find_si(&ip, 0, PROTO_TLS);
418 419
 	else
419 420
 #endif
420
-		si=find_tcp_si(&my_name);
421
+		si=find_si(&ip, 0, PROTO_TCP);
421 422
 
422 423
 	if (si==0){
423 424
 		LOG(L_ERR, "ERROR: tcp_connect: could not find corresponding"