Browse code

- mcast fixes: avoid trying to send from multicast listening sockets (the kernel will fix it, but in a non-ser deterministic way, e.g. the sent packet might have as source ip and address on which we don't listen): - get_send_socket() will ignore a forced mcast socket - msg_send() will ignore a mcast source socket and it will automatically choose another one

Andrei Pelinescu-Onciul authored on 08/10/2007 13:29:41
Showing 2 changed files
... ...
@@ -52,6 +52,8 @@
52 52
  *  2006-04-21  basic comp via param support (andrei)
53 53
  *  2006-07-31  forward_request can resolve destination on its own, uses the 
54 54
  *              dns cache and falls back on send error to other ips (andrei)
55
+ *  2007-10-08  get_send_socket() will ignore force_send_socket if the forced
56
+ *               socket is multicast (andrei)
55 57
  */
56 58
 
57 59
 
... ...
@@ -89,6 +91,7 @@
89 89
 #ifdef USE_DST_BLACKLIST
90 90
 #include "dst_blacklist.h"
91 91
 #endif
92
+#include "compiler_opt.h"
92 93
 
93 94
 #ifdef DEBUG_DMALLOC
94 95
 #include <dmalloc.h>
... ...
@@ -158,24 +161,27 @@ struct socket_info* get_send_socket(struct sip_msg *msg,
158 158
 	struct socket_info* send_sock;
159 159
 	
160 160
 	/* check if send interface is not forced */
161
-	if (msg && msg->force_send_socket){
162
-		if (msg->force_send_socket->proto!=proto){
161
+	if (unlikely(msg && msg->force_send_socket)){
162
+		if (unlikely(msg->force_send_socket->proto!=proto)){
163 163
 			DBG("get_send_socket: force_send_socket of different proto"
164 164
 					" (%d)!\n", proto);
165 165
 			msg->force_send_socket=find_si(&(msg->force_send_socket->address),
166 166
 											msg->force_send_socket->port_no,
167 167
 											proto);
168
-			if (msg->force_send_socket == 0){
168
+			if (unlikely(msg->force_send_socket == 0)){
169 169
 				LOG(L_WARN, "WARNING: get_send_socket: "
170 170
 						"protocol/port mismatch\n");
171 171
 				goto not_forced;
172 172
 			}
173 173
 		}
174
-		if (msg->force_send_socket->socket!=-1)
174
+		if (likely((msg->force_send_socket->socket!=-1) &&
175
+					!(msg->force_send_socket->flags & SI_IS_MCAST)))
175 176
 				return msg->force_send_socket;
176
-		else
177
-			LOG(L_WARN, "WARNING: get_send_socket: not listening"
178
-						 " on the requested socket, no fork mode?\n");
177
+		else{
178
+			if (!(msg->force_send_socket->flags & SI_IS_MCAST))
179
+				LOG(L_WARN, "WARNING: get_send_socket: not listening"
180
+							 " on the requested socket, no fork mode?\n");
181
+		}
179 182
 	};
180 183
 not_forced:
181 184
 	if (mhomed && proto==PROTO_UDP){
... ...
@@ -35,6 +35,8 @@
35 35
  *  2003-04-15  added tcp_disable support (andrei)
36 36
  *  2006-04-12  reduced msg_send() parameter list: it uses now a struct 
37 37
  *               dest_info param. (andrei)
38
+ *  2007-10-08  msg_send() will ignore a mcast send_sock and choose another
39
+ *               one by itself (andrei)
38 40
  */
39 41
 
40 42
 
... ...
@@ -54,6 +56,8 @@
54 54
 #include "tcp_server.h"
55 55
 #endif
56 56
 
57
+#include "compiler_opt.h"
58
+
57 59
 
58 60
 
59 61
 struct socket_info* get_send_socket(struct sip_msg* msg,
... ...
@@ -79,7 +83,8 @@ int forward_reply( struct sip_msg* msg);
79 79
 
80 80
 /* params:
81 81
  * dst = struct dest_info containing:
82
- *    send_sock = 0 if not known (e.g. for udp in some cases), non-0 otherwise
82
+ *    send_sock = 0 if not known (e.g. for udp in some cases), non-0 otherwise;
83
+ *                if 0 or mcast a new send_sock will be automatically choosen
83 84
  *    proto = TCP|UDP
84 85
  *    to = destination (sockaddr_union)
85 86
  *    id = only used on tcp, it will force sending on connection "id" if id!=0 
... ...
@@ -90,15 +95,20 @@ int forward_reply( struct sip_msg* msg);
90 90
  * returns: 0 if ok, -1 on error*/
91 91
 static inline int msg_send(struct dest_info* dst, char* buf, int len)
92 92
 {
93
+	struct dest_info new_dst;
93 94
 	
94
-	if (dst->proto==PROTO_UDP){
95
-		if (dst->send_sock==0) 
96
-			dst->send_sock=get_send_socket(0, &dst->to, dst->proto);
97
-		if (dst->send_sock==0){
98
-			LOG(L_ERR, "msg_send: ERROR: no sending socket found\n");
99
-			goto error;
95
+	if (likely(dst->proto==PROTO_UDP)){
96
+		if (unlikely((dst->send_sock==0) || 
97
+					(dst->send_sock->flags & SI_IS_MCAST))){
98
+			new_dst=*dst;
99
+			new_dst.send_sock=get_send_socket(0, &dst->to, dst->proto);
100
+			if (unlikely(new_dst.send_sock==0)){
101
+				LOG(L_ERR, "msg_send: ERROR: no sending socket found\n");
102
+				goto error;
103
+			}
104
+			dst=&new_dst;
100 105
 		}
101
-		if (udp_send(dst, buf, len)==-1){
106
+		if (unlikely(udp_send(dst, buf, len)==-1)){
102 107
 			STATS_TX_DROPS;
103 108
 			LOG(L_ERR, "msg_send: ERROR: udp_send failed\n");
104 109
 			goto error;
... ...
@@ -106,13 +116,13 @@ static inline int msg_send(struct dest_info* dst, char* buf, int len)
106 106
 	}
107 107
 #ifdef USE_TCP
108 108
 	else if (dst->proto==PROTO_TCP){
109
-		if (tcp_disable){
109
+		if (unlikely(tcp_disable)){
110 110
 			STATS_TX_DROPS;
111 111
 			LOG(L_WARN, "msg_send: WARNING: attempt to send on tcp and tcp"
112 112
 					" support is disabled\n");
113 113
 			goto error;
114 114
 		}else{
115
-			if (tcp_send(dst, 0, buf, len)<0){
115
+			if (unlikely(tcp_send(dst, 0, buf, len)<0)){
116 116
 				STATS_TX_DROPS;
117 117
 				LOG(L_ERR, "msg_send: ERROR: tcp_send failed\n");
118 118
 				goto error;
... ...
@@ -121,13 +131,13 @@ static inline int msg_send(struct dest_info* dst, char* buf, int len)
121 121
 	}
122 122
 #ifdef USE_TLS
123 123
 	else if (dst->proto==PROTO_TLS){
124
-		if (tls_disable){
124
+		if (unlikely(tls_disable)){
125 125
 			STATS_TX_DROPS;
126 126
 			LOG(L_WARN, "msg_send: WARNING: attempt to send on tls and tls"
127 127
 					" support is disabled\n");
128 128
 			goto error;
129 129
 		}else{
130
-			if (tcp_send(dst, 0, buf, len)<0){
130
+			if (unlikely(tcp_send(dst, 0, buf, len)<0)){
131 131
 				STATS_TX_DROPS;
132 132
 				LOG(L_ERR, "msg_send: ERROR: tcp_send failed\n");
133 133
 				goto error;