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 91
 #ifdef USE_DST_BLACKLIST
90 92
 #include "dst_blacklist.h"
91 93
 #endif
94
+#include "compiler_opt.h"
92 95
 
93 96
 #ifdef DEBUG_DMALLOC
94 97
 #include <dmalloc.h>
... ...
@@ -158,24 +161,27 @@ struct socket_info* get_send_socket(struct sip_msg *msg,
158 161
 	struct socket_info* send_sock;
159 162
 	
160 163
 	/* check if send interface is not forced */
161
-	if (msg && msg->force_send_socket){
162
-		if (msg->force_send_socket->proto!=proto){
164
+	if (unlikely(msg && msg->force_send_socket)){
165
+		if (unlikely(msg->force_send_socket->proto!=proto)){
163 166
 			DBG("get_send_socket: force_send_socket of different proto"
164 167
 					" (%d)!\n", proto);
165 168
 			msg->force_send_socket=find_si(&(msg->force_send_socket->address),
166 169
 											msg->force_send_socket->port_no,
167 170
 											proto);
168
-			if (msg->force_send_socket == 0){
171
+			if (unlikely(msg->force_send_socket == 0)){
169 172
 				LOG(L_WARN, "WARNING: get_send_socket: "
170 173
 						"protocol/port mismatch\n");
171 174
 				goto not_forced;
172 175
 			}
173 176
 		}
174
-		if (msg->force_send_socket->socket!=-1)
177
+		if (likely((msg->force_send_socket->socket!=-1) &&
178
+					!(msg->force_send_socket->flags & SI_IS_MCAST)))
175 179
 				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");
180
+		else{
181
+			if (!(msg->force_send_socket->flags & SI_IS_MCAST))
182
+				LOG(L_WARN, "WARNING: get_send_socket: not listening"
183
+							 " on the requested socket, no fork mode?\n");
184
+		}
179 185
 	};
180 186
 not_forced:
181 187
 	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 56
 #include "tcp_server.h"
55 57
 #endif
56 58
 
59
+#include "compiler_opt.h"
60
+
57 61
 
58 62
 
59 63
 struct socket_info* get_send_socket(struct sip_msg* msg,
... ...
@@ -79,7 +83,8 @@ int forward_reply( struct sip_msg* msg);
79 83
 
80 84
 /* params:
81 85
  * dst = struct dest_info containing:
82
- *    send_sock = 0 if not known (e.g. for udp in some cases), non-0 otherwise
86
+ *    send_sock = 0 if not known (e.g. for udp in some cases), non-0 otherwise;
87
+ *                if 0 or mcast a new send_sock will be automatically choosen
83 88
  *    proto = TCP|UDP
84 89
  *    to = destination (sockaddr_union)
85 90
  *    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 95
  * returns: 0 if ok, -1 on error*/
91 96
 static inline int msg_send(struct dest_info* dst, char* buf, int len)
92 97
 {
98
+	struct dest_info new_dst;
93 99
 	
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;
100
+	if (likely(dst->proto==PROTO_UDP)){
101
+		if (unlikely((dst->send_sock==0) || 
102
+					(dst->send_sock->flags & SI_IS_MCAST))){
103
+			new_dst=*dst;
104
+			new_dst.send_sock=get_send_socket(0, &dst->to, dst->proto);
105
+			if (unlikely(new_dst.send_sock==0)){
106
+				LOG(L_ERR, "msg_send: ERROR: no sending socket found\n");
107
+				goto error;
108
+			}
109
+			dst=&new_dst;
100 110
 		}
101
-		if (udp_send(dst, buf, len)==-1){
111
+		if (unlikely(udp_send(dst, buf, len)==-1)){
102 112
 			STATS_TX_DROPS;
103 113
 			LOG(L_ERR, "msg_send: ERROR: udp_send failed\n");
104 114
 			goto error;
... ...
@@ -106,13 +116,13 @@ static inline int msg_send(struct dest_info* dst, char* buf, int len)
106 116
 	}
107 117
 #ifdef USE_TCP
108 118
 	else if (dst->proto==PROTO_TCP){
109
-		if (tcp_disable){
119
+		if (unlikely(tcp_disable)){
110 120
 			STATS_TX_DROPS;
111 121
 			LOG(L_WARN, "msg_send: WARNING: attempt to send on tcp and tcp"
112 122
 					" support is disabled\n");
113 123
 			goto error;
114 124
 		}else{
115
-			if (tcp_send(dst, 0, buf, len)<0){
125
+			if (unlikely(tcp_send(dst, 0, buf, len)<0)){
116 126
 				STATS_TX_DROPS;
117 127
 				LOG(L_ERR, "msg_send: ERROR: tcp_send failed\n");
118 128
 				goto error;
... ...
@@ -121,13 +131,13 @@ static inline int msg_send(struct dest_info* dst, char* buf, int len)
121 131
 	}
122 132
 #ifdef USE_TLS
123 133
 	else if (dst->proto==PROTO_TLS){
124
-		if (tls_disable){
134
+		if (unlikely(tls_disable)){
125 135
 			STATS_TX_DROPS;
126 136
 			LOG(L_WARN, "msg_send: WARNING: attempt to send on tls and tls"
127 137
 					" support is disabled\n");
128 138
 			goto error;
129 139
 		}else{
130
-			if (tcp_send(dst, 0, buf, len)<0){
140
+			if (unlikely(tcp_send(dst, 0, buf, len)<0)){
131 141
 				STATS_TX_DROPS;
132 142
 				LOG(L_ERR, "msg_send: ERROR: tcp_send failed\n");
133 143
 				goto error;