Browse code

- split init_sock_opt into init_sock_opt, called for new sockets (e.g. on connect) and init_sock_opt_accept() called only for sockets created as a result of an accept and which inherit the options from the "parent" listening socket (which the O_NONBLOCK exception for which no behaviour is specified and which is seems to be inherithed on BSDs and solaris, but not on linux). - init_sock_opt sets also SO_REUSEADDR

Andrei Pelinescu-Onciul authored on 27/08/2007 21:48:56
Showing 1 changed files
... ...
@@ -78,6 +78,9 @@
78 78
  *  2007-07-26   tcp_send() and tcpconn_get() can now use a specified source
79 79
  *                addr./port (andrei)
80 80
  *  2007-08-23   getsockname() for INADDR_ANY(SI_IS_ANY) sockets (andrei)
81
+ *  2007-08-27   split init_sock_opt into a lightweight init_sock_opt_accept() 
82
+ *               used when accepting connections and init_sock_opt used for 
83
+ *               connect/ new sockets (andrei)
81 84
  */
82 85
 
83 86
 
... ...
@@ -235,7 +238,9 @@ int tcp_set_src_addr(struct ip_addr* ip)
235 235
 
236 236
 
237 237
 
238
-/* set all socket/fd options:  disable nagle, tos lowdelay, non-blocking
238
+/* set all socket/fd options for new sockets (e.g. before connect): 
239
+ *  disable nagle, tos lowdelay, reuseaddr, non-blocking
240
+ *
239 241
  * return -1 on error */
240 242
 static int init_sock_opt(int s)
241 243
 {
... ...
@@ -257,6 +262,16 @@ static int init_sock_opt(int s)
257 257
 				strerror(errno));
258 258
 		/* continue since this is not critical */
259 259
 	}
260
+#if  !defined(TCP_DONT_REUSEADDR) 
261
+	optval=1;
262
+	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
263
+						(void*)&optval, sizeof(optval))==-1){
264
+		LOG(L_ERR, "ERROR: setsockopt SO_REUSEADDR %s\n",
265
+				strerror(errno));
266
+		/* continue, not critical */
267
+	}
268
+#endif /* !TCP_DONT_REUSEADDR */
269
+	
260 270
 	/* non-blocking */
261 271
 	flags=fcntl(s, F_GETFL);
262 272
 	if (flags==-1){
... ...
@@ -276,6 +291,42 @@ error:
276 276
 
277 277
 
278 278
 
279
+/* set all socket/fd options for "accepted" sockets 
280
+ *  only nonblocking is set since the rest is inherited from the
281
+ *  "parent" (listening) socket
282
+ *  Note: setting O_NONBLOCK is required on linux but it's not needed on
283
+ *        BSD and possibly solaris (where the flag is inherited from the 
284
+ *        parent socket). However since there is no standard document 
285
+ *        requiring a specific behaviour in this case it's safer to always set
286
+ *        it (at least for now)  --andrei
287
+ *  TODO: check on which OSes  O_NONBLOCK is inherited and make this 
288
+ *        function a nop.
289
+ *
290
+ * return -1 on error */
291
+static int init_sock_opt_accept(int s)
292
+{
293
+	int flags;
294
+	
295
+	/* non-blocking */
296
+	flags=fcntl(s, F_GETFL);
297
+	if (flags==-1){
298
+		LOG(L_ERR, "ERROR: init_sock_opt_accept: fnctl failed: (%d) %s\n",
299
+				errno, strerror(errno));
300
+		goto error;
301
+	}
302
+	if (fcntl(s, F_SETFL, flags|O_NONBLOCK)==-1){
303
+		LOG(L_ERR, "ERROR: init_sock_opt_accept: "
304
+					"fcntl: set non-blocking failed: (%d) %s\n",
305
+					errno, strerror(errno));
306
+		goto error;
307
+	}
308
+	return 0;
309
+error:
310
+	return -1;
311
+}
312
+
313
+
314
+
279 315
 /* blocking connect on a non-blocking fd; it will timeout after
280 316
  * tcp_connect_timeout 
281 317
  * if BLOCKING_USE_SELECT and HAVE_SELECT are defined it will internally
... ...
@@ -1632,7 +1683,7 @@ static inline int handle_new_connect(struct socket_info* si)
1632 1632
 		close(new_sock);
1633 1633
 		return 1; /* success, because the accept was succesfull */
1634 1634
 	}
1635
-	if (init_sock_opt(new_sock)<0){
1635
+	if (init_sock_opt_accept(new_sock)<0){
1636 1636
 		LOG(L_ERR, "ERROR: handle_new_connect: init_sock_opt failed\n");
1637 1637
 		close(new_sock);
1638 1638
 		return 1; /* success, because the accept was succesfull */