Преглед на файлове

- 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 преди 21 години
родител
ревизия
a35ad52c2d
променени са 17 файла, в които са добавени 108 реда и са изтрити 38 реда
  1. 1 1
      Makefile.defs
  2. 1 1
      action.c
  3. 24 3
      forward.c
  4. 4 2
      forward.h
  5. 1 1
      modules/tm/t_fwd.c
  6. 1 1
      modules/tm/t_lookup.c
  7. 1 1
      modules/tm/t_msgbuilder.c
  8. 9 3
      modules/tm/t_reply.c
  9. 2 1
      modules/tm/uac.c
  10. 1 1
      modules/tm/uac_fifo.c
  11. 1 1
      modules/tm/uac_unixsock.c
  12. 3 2
      modules/tm/ut.h
  13. 1 1
      parser/msg_parser.c
  14. 3 0
      parser/msg_parser.h
  15. 48 1
      socket_info.c
  16. 2 0
      socket_info.h
  17. 5 18
      tcp_main.c

+ 1 - 1
Makefile.defs

@@ -50,7 +50,7 @@ MAIN_NAME=ser
 VERSION = 0
 PATCHLEVEL = 8
 SUBLEVEL =   99
-EXTRAVERSION = -dev12
+EXTRAVERSION = -dev13
 
 RELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 OS = $(shell uname -s | sed -e s/SunOS/solaris/ | tr "[A-Z]" "[a-z]")

+ 1 - 1
action.c

@@ -241,7 +241,7 @@ int do_action(struct action* a, struct sip_msg* msg)
 				p->tx_bytes+=msg->len;
 				if (a->type==SEND_T){
 					/*udp*/
-					send_sock=get_send_socket(to, PROTO_UDP);
+					send_sock=get_send_socket(msg, to, PROTO_UDP);
 					if (send_sock!=0){
 						ret=udp_send(send_sock, msg->buf, msg->len, to);
 					}else{

+ 24 - 3
forward.c

@@ -45,6 +45,7 @@
  *  2003-10-21  check_self updated to handle proto (andrei)
  *  2003-10-24  converted to the new socket_info lists (andrei)
  *  2004-10-10  modified check_self to use grep_sock_info (andrei)
+ *  2004-11-08  added force_send_socket support in get_send_socket (andrei)
  */
 
 
@@ -79,6 +80,8 @@
 #include <dmalloc.h>
 #endif
 
+
+
 /* return a socket_info_pointer to the sending socket; as opposed to
  * get_send_socket, which returns process's default socket, get_out_socket
  * attempts to determine the outbound interface which will be used;
@@ -153,11 +156,29 @@ found:
 
 
 /* returns a socket_info pointer to the sending socket or 0 on error
- * params: destination socket_union pointer
+ * params: sip msg (can be null), destination socket_union pointer, protocol
+ * if msg!=null and msg->force_send_socket, the force_send_socket will be
+ * used
  */
-struct socket_info* get_send_socket(union sockaddr_union* to, int proto)
+struct socket_info* get_send_socket(struct sip_msg *msg, 
+										union sockaddr_union* to, int proto)
 {
 	struct socket_info* send_sock;
+	
+	/* check if send interface is not forced */
+	if (msg && msg->force_send_socket){
+		if (msg->force_send_socket->proto!=proto){
+			DBG("get_send_socket: force_send_socket of different proto"
+					" (%d)!\n", proto);
+			msg->force_send_socket=find_si(&(msg->force_send_socket->address),
+											msg->force_send_socket->port_no,
+											proto);
+		}
+		if (msg->force_send_socket) 
+			return msg->force_send_socket;
+		else
+			LOG(L_WARN, "WARNING: get_send_socket: protocol/port mismatch\n");
+	};
 
 	if (mhomed && proto==PROTO_UDP) return get_out_socket(to, proto);
 
@@ -278,7 +299,7 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p, int proto)
 	p->tx_bytes+=len;
 	
 
-	send_sock=get_send_socket(to, proto);
+	send_sock=get_send_socket(msg, to, proto);
 	if (send_sock==0){
 		LOG(L_ERR, "forward_req: ERROR: cannot forward to af %d, proto %d "
 				"no corresponding listening socket\n", to->s.sa_family, proto);

+ 4 - 2
forward.h

@@ -53,7 +53,9 @@
 #endif
 
 
-struct socket_info* get_send_socket(union sockaddr_union* su, int proto);
+
+struct socket_info* get_send_socket(struct sip_msg* msg,
+									union sockaddr_union* su, int proto);
 struct socket_info* get_out_socket(union sockaddr_union* to, int proto);
 int check_self(str* host, unsigned short port, unsigned short proto);
 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,
 {
 	
 	if (proto==PROTO_UDP){
-		if (send_sock==0) send_sock=get_send_socket(to, proto);
+		if (send_sock==0) send_sock=get_send_socket(0, to, proto);
 		if (send_sock==0){
 			LOG(L_ERR, "msg_send: ERROR: no sending socket found\n");
 			goto error;

+ 1 - 1
modules/tm/t_fwd.c

@@ -215,7 +215,7 @@ int add_uac( struct cell *t, struct sip_msg *request, str *uri, str* next_hop,
 	hostent2su( &to, &proxy->host, proxy->addr_idx, 
 		proxy->port ? proxy->port:SIP_PORT);
 
-	send_sock=get_send_socket( &to , proto);
+	send_sock=get_send_socket( request, &to , proto);
 	if (send_sock==0) {
 		LOG(L_ERR, "ERROR: add_uac: can't fwd to af %d, proto %d "
 			" (no corresponding listening socket)\n",

+ 1 - 1
modules/tm/t_lookup.c

@@ -933,7 +933,7 @@ int init_rb( struct retr_buf *rb, struct sip_msg *msg)
 	*/
 	backup_mhomed=mhomed;
 	mhomed=0;
-	send_sock=get_send_socket(&rb->dst.to, proto);
+	send_sock=get_send_socket(msg, &rb->dst.to, proto);
 	mhomed=backup_mhomed;
 	if (send_sock==0) {
 		LOG(L_ERR, "ERROR: init_rb: cannot fwd to af %d, proto %d "

+ 1 - 1
modules/tm/t_msgbuilder.c

@@ -408,7 +408,7 @@ char *build_dlg_ack(struct sip_msg* rpl, struct cell *Trans, unsigned int branch
 	
 	
 	     /* via */
-	send_sock = uri2sock(next_hop, &to_su, PROTO_NONE);
+	send_sock = uri2sock(rpl, next_hop, &to_su, PROTO_NONE);
 	if (!send_sock) {
 		LOG(L_ERR, "build_dlg_ack: no socket found\n");
 		goto error;

+ 9 - 3
modules/tm/t_reply.c

@@ -309,7 +309,8 @@ static char *build_local_ack(struct sip_msg* rpl, struct cell *trans, int branch
       * The function is used to send a localy generated ACK to INVITE
       * (tm generates the ACK on behalf of application using UAC
       */
-static int send_local_ack(str* next_hop, char* ack, int ack_len)
+static int send_local_ack(struct sip_msg* msg, str* next_hop,
+							char* ack, int ack_len)
 {
 	struct socket_info* send_sock;
 	union sockaddr_union to_su;
@@ -319,7 +320,7 @@ static int send_local_ack(str* next_hop, char* ack, int ack_len)
 		return -1;
 	}
 	
-	send_sock = uri2sock(next_hop, &to_su, PROTO_NONE);
+	send_sock = uri2sock(msg, next_hop, &to_su, PROTO_NONE);
 	if (!send_sock) {
 		LOG(L_ERR, "send_local_ack: no socket found\n");
 		return -1;
@@ -480,6 +481,7 @@ static inline void faked_env( struct cell *t,struct sip_msg *msg)
 	static struct cell *backup_t;
 	static unsigned int backup_msgid;
 	static struct usr_avp **backup_list;
+	static struct socket_info* backup_si;
 
 	if (msg) {
 		/* 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)
 		set_t(t);
 		/* make available the avp list from transaction */
 		backup_list = set_avp_list( &t->user_avps );
+		/* set default send address to the saved value */
+		backup_si=bind_address;
+		bind_address=t->uac[0].request.dst.send_sock;
 	} else {
 		/* restore original environment */
 		set_t(backup_t);
@@ -509,6 +514,7 @@ static inline void faked_env( struct cell *t,struct sip_msg *msg)
 		rmode=backup_mode;
 		/* restore original avp list */
 		set_avp_list( backup_list );
+		bind_address=backup_si;
 	}
 }
 
@@ -1255,7 +1261,7 @@ int reply_received( struct sip_msg  *p_msg )
 		} else if ((t->flags & T_IS_LOCAL_FLAG) && msg_status >= 200) {
 			ack = build_local_ack(p_msg, t, branch, &ack_len, &next_hop);
 			if (ack) {
-				if (send_local_ack(&next_hop, ack, ack_len) < 0) {
+				if (send_local_ack(p_msg, &next_hop, ack, ack_len) < 0) {
 					LOG(L_ERR, "Error while sending local ACK\n");
 				}
 				shm_free(ack);

+ 2 - 1
modules/tm/uac.c

@@ -185,7 +185,8 @@ int t_uac(str* method, str* headers, str* body, dlg_t* dialog,
 
 	DBG("DEBUG:tm:t_uac: next_hop=<%.*s>\n",dialog->hooks.next_hop->len,
 			dialog->hooks.next_hop->s);
-	send_sock = uri2sock(dialog->hooks.next_hop, &to_su, PROTO_NONE);
+	/* it's a new message, so we will take the default socket */
+	send_sock = uri2sock(0, dialog->hooks.next_hop, &to_su, PROTO_NONE);
 	if (!send_sock) {
 		ret=ser_error;
 		LOG(L_ERR, "t_uac: no socket found\n");

+ 1 - 1
modules/tm/uac_fifo.c

@@ -267,7 +267,7 @@ static char *get_hfblock(str *uri, struct hdr_field *hf, int *l, int proto)
 						if (!new) goto error;
 						/* substitute */
 						if (!sock_name) {
-							send_sock=uri2sock( uri, &to_su, proto );
+							send_sock=uri2sock(0, uri, &to_su, proto );
 							if (!send_sock) {
 								LOG(L_ERR, "ERROR: get_hfblock: send_sock failed\n");
 								goto error;

+ 1 - 1
modules/tm/uac_unixsock.c

@@ -294,7 +294,7 @@ static char *get_hfblock(str *uri, struct hdr_field *hf, int *l, int proto)
 					if (!new_str(begin, frag_len, &last, &total_len)) goto error;
 					     /* substitute */
 					if (!sock_name) {
-						send_sock = uri2sock(uri, &to_su, proto);
+						send_sock = uri2sock(0, uri, &to_su, proto);
 						if (!send_sock) {
 							LOG(L_ERR, "ERROR: get_hfblock: send_sock failed\n");
 							goto error;

+ 3 - 2
modules/tm/ut.h

@@ -133,7 +133,8 @@ inline static struct proxy_l *uri2proxy( str *uri, int proto )
 /*
  * Convert a URI into socket_info
  */
-static inline struct socket_info *uri2sock(str *uri, union sockaddr_union *to_su, int proto)
+static inline struct socket_info *uri2sock(struct sip_msg* msg, str *uri,
+									union sockaddr_union *to_su, int proto)
 {
 	struct proxy_l *proxy;
 	struct socket_info* send_sock;
@@ -148,7 +149,7 @@ static inline struct socket_info *uri2sock(str *uri, union sockaddr_union *to_su
 	hostent2su(to_su, &proxy->host, proxy->addr_idx, 
 		   (proxy->port) ? proxy->port : SIP_PORT);
 			/* we use proxy->proto since uri2proxy just set it correctly*/
-	send_sock = get_send_socket(to_su, proxy->proto);
+	send_sock = get_send_socket(msg, to_su, proxy->proto);
 	if (!send_sock) {
 		LOG(L_ERR, "ERROR: uri2sock: no corresponding socket for af %d\n", 
 		    to_su->s.sa_family);

+ 1 - 1
parser/msg_parser.c

@@ -91,7 +91,7 @@ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
 	}
 
 	/* eliminate leading whitespace */
-	tmp=eat_lws_end(tmp, end);
+	/* tmp=eat_lws_end(tmp, end); not allowed anyway --andrei */
 	if (tmp>=end) {
 		LOG(L_ERR, "ERROR: get_hdr_field: HF empty\n");
 		goto error;

+ 3 - 0
parser/msg_parser.h

@@ -36,6 +36,7 @@
  *  2003-04-11  updated the  sip_uri structure (lots of fields added) (andrei)
  *  2003-04-12  added msg_flags to sip_msg (andrei)
  *  2003-11-02  added diversion header field to sip_msg (jh)
+ *  2004-11-08  added force_send_socket (andrei)
  */
 
 
@@ -237,6 +238,8 @@ struct sip_msg {
 	flag_t flags;	
 	str set_global_address;
 	str set_global_port;
+	struct socket_info* force_send_socket; /* force sending on this socket,
+											  if ser */
 };
 
 /* pointer to a fakes message which was never received ;

+ 48 - 1
socket_info.c

@@ -33,6 +33,7 @@
  * --------
  *  2003-10-22  created by andrei
  *  2004-10-10  added grep_sock_info (andrei)
+ *  2004-11-08  added find_si (andrei)
  */
 
 
@@ -205,7 +206,6 @@ struct socket_info* grep_sock_info(str* host, unsigned short port,
 #ifdef USE_IPV6
 	struct ip_addr* ip6;
 #endif
-
 	h_len=host->len;
 	hname=host->s;
 #ifdef USE_IPV6
@@ -279,6 +279,53 @@ found:
 
 
 
+/* checks if the proto: ip:port is one of the address we listen on
+ * and returns the corresponding socket_info structure.
+ * (same as grep_socket_info, but use ip addr instead)
+ * if port==0, the  port number is ignored
+ * if proto==0 (PROTO_NONE) the protocol is ignored
+ * returns  0 if not found
+ * WARNING: uses str2ip6 so it will overwrite any previous
+ *  unsaved result of this function (static buffer)
+ */
+struct socket_info* find_si(struct ip_addr* ip, unsigned short port,
+												unsigned short proto)
+{
+	struct socket_info* si;
+	struct socket_info** list;
+	unsigned short c_proto;
+	
+	c_proto=proto?proto:PROTO_UDP;
+	do{
+		/* get the proper sock_list */
+		if (c_proto==PROTO_NONE)
+			list=&udp_listen;
+		else
+			list=get_sock_info_list(c_proto);
+	
+		if (list==0){
+			LOG(L_WARN, "WARNING: grep_sock_info: "
+						"unknown proto %d\n", c_proto);
+			goto not_found; /* false */
+		}
+		for (si=*list; si; si=si->next){
+			if (port) {
+				if (si->port_no!=port) {
+					continue;
+				}
+			}
+			if (ip_addr_cmp(ip, &si->address))
+				goto found;
+		}
+	}while( (proto==0) && (c_proto=next_proto(c_proto)) );
+not_found:
+	return 0;
+found:
+	return si;
+}
+
+
+
 /* adds a new sock_info structure to the corresponding list
  * return  0 on success, -1 on error */
 int new_sock2list(char* name, unsigned short port, unsigned short proto,

+ 2 - 0
socket_info.h

@@ -59,6 +59,8 @@ void print_aliases();
 
 struct socket_info* grep_sock_info(str* host, unsigned short port,
 										unsigned short proto);
+struct socket_info* find_si(struct ip_addr* ip, unsigned short port,
+												unsigned short proto);
 
 /* helper function:
  * returns next protocol, if the last one is reached return 0

+ 5 - 18
tcp_main.c

@@ -51,6 +51,7 @@
  *  2003-11-17  handle_new_connect & tcp_connect will close the 
  *              new socket if tcpconn_new return 0 (e.g. out of mem) (andrei)
  *  2003-11-28  tcp_blocking_write & tcp_blocking_connect added (andrei)
+ *  2004-11-08  dropped find_tcp_si and replaced with find_si (andrei)
  */
 
 
@@ -368,22 +369,6 @@ error:
 
 
 
-
-struct socket_info* find_tcp_si(union sockaddr_union* s)
-{
-	struct ip_addr ip;
-	struct socket_info* si;
-	
-	su2ip_addr(&ip, s);
-	for (si=tcp_listen; si; si=si->next)
-		if (ip_addr_cmp(&ip, &si->address)){
-			/* found it, we use first match */
-			return si;
-		}
-	return 0; /* no match */
-}
-
-
 struct tcp_connection* tcpconn_connect(union sockaddr_union* server, int type)
 {
 	int s;
@@ -391,6 +376,7 @@ struct tcp_connection* tcpconn_connect(union sockaddr_union* server, int type)
 	union sockaddr_union my_name;
 	socklen_t my_name_len;
 	struct tcp_connection* con;
+	struct ip_addr ip;
 
 	s=socket(AF2PF(server->s.sa_family), SOCK_STREAM, 0);
 	if (s==-1){
@@ -412,12 +398,13 @@ struct tcp_connection* tcpconn_connect(union sockaddr_union* server, int type)
 				strerror(errno), errno);
 		si=0; /* try to go on */
 	}
+	su2ip_addr(&ip, &my_name);
 #ifdef USE_TLS
 	if (type==PROTO_TLS)
-		si=find_tls_si(&my_name);
+		si=find_si(&ip, 0, PROTO_TLS);
 	else
 #endif
-		si=find_tcp_si(&my_name);
+		si=find_si(&ip, 0, PROTO_TCP);
 
 	if (si==0){
 		LOG(L_ERR, "ERROR: tcp_connect: could not find corresponding"