Browse Source

Restructure confusingly long if statement in set_ports_options

bel 10 years ago
parent
commit
ff7e392128
1 changed files with 163 additions and 106 deletions
  1. 163 106
      src/civetweb.c

+ 163 - 106
src/civetweb.c

@@ -2379,6 +2379,7 @@ mg_stat(struct mg_connection *conn, const char *path, struct file *filep)
 {
 {
 	wchar_t wbuf[PATH_MAX];
 	wchar_t wbuf[PATH_MAX];
 	WIN32_FILE_ATTRIBUTE_DATA info;
 	WIN32_FILE_ATTRIBUTE_DATA info;
+	time_t creation_time;
 
 
 	if (!is_file_in_memory(conn, path, filep)) {
 	if (!is_file_in_memory(conn, path, filep)) {
 		to_unicode(path, wbuf, ARRAY_SIZE(wbuf));
 		to_unicode(path, wbuf, ARRAY_SIZE(wbuf));
@@ -2392,9 +2393,8 @@ mg_stat(struct mg_connection *conn, const char *path, struct file *filep)
 			 * modification time, e.g. when a file is copied.
 			 * modification time, e.g. when a file is copied.
 			 * Since the Last-Modified timestamp is used for caching
 			 * Since the Last-Modified timestamp is used for caching
 			 * it should be based on the most recent timestamp. */
 			 * it should be based on the most recent timestamp. */
-			time_t creation_time =
-			    SYS2UNIX_TIME(info.ftCreationTime.dwLowDateTime,
-			                  info.ftCreationTime.dwHighDateTime);
+			creation_time = SYS2UNIX_TIME(info.ftCreationTime.dwLowDateTime,
+			                              info.ftCreationTime.dwHighDateTime);
 			if (creation_time > filep->modification_time) {
 			if (creation_time > filep->modification_time) {
 				filep->modification_time = creation_time;
 				filep->modification_time = creation_time;
 			}
 			}
@@ -8269,123 +8269,180 @@ static int parse_port_string(const struct vec *vec, struct socket *so)
 
 
 static int set_ports_option(struct mg_context *ctx)
 static int set_ports_option(struct mg_context *ctx)
 {
 {
-	if (ctx) {
-		const char *list = ctx->config[LISTENING_PORTS];
-		int on = 1, success = 1;
+	const char *list = ctx->config[LISTENING_PORTS];
+	int on = 1;
 #if defined(USE_IPV6)
 #if defined(USE_IPV6)
-		int off = 0;
+	int off = 0;
 #endif
 #endif
-		struct vec vec;
-		struct socket so, *ptr;
+	struct vec vec;
+	struct socket so, *ptr;
 
 
-		in_port_t *portPtr;
-		union usa usa;
-		socklen_t len;
+	in_port_t *portPtr;
+	union usa usa;
+	socklen_t len;
 
 
-		memset(&so, 0, sizeof(so));
-		memset(&usa, 0, sizeof(usa));
-		len = sizeof(usa);
+	int portsTotal = 0;
+	int portsOk = 0;
+
+	if (!ctx) {
+		return 0;
+	}
+
+	memset(&so, 0, sizeof(so));
+	memset(&usa, 0, sizeof(usa));
+	len = sizeof(usa);
+
+	while ((list = next_option(list, &vec, NULL)) != NULL) {
+
+		portsTotal++;
+
+		if (!parse_port_string(&vec, &so)) {
+			mg_cry(fc(ctx),
+			       "%.*s: invalid port spec (entry %i). Expecting list of: %s",
+			       (int)vec.len,
+			       vec.ptr,
+			       portsTotal,
+			       "[IP_ADDRESS:]PORT[s|r]");
+			continue;
+		}
+
+		if (so.is_ssl && ctx->ssl_ctx == NULL) {
+			mg_cry(fc(ctx),
+			       "Cannot add SSL socket (entry %i). Is -ssl_certificate "
+			       "option set?",
+			       portsTotal);
+			continue;
+		}
+
+		if ((so.sock = socket(so.lsa.sa.sa_family, SOCK_STREAM, 6)) ==
+		    INVALID_SOCKET) {
+			mg_cry(fc(ctx), "cannot create socket (entry %i)", portsTotal);
+			continue;
+		}
 
 
-		while (success && (list = next_option(list, &vec, NULL)) != NULL) {
-			if (!parse_port_string(&vec, &so)) {
-				mg_cry(fc(ctx),
-				       "%s: %.*s: invalid port spec. Expecting list of: %s",
-				       __func__,
-				       (int)vec.len,
-				       vec.ptr,
-				       "[IP_ADDRESS:]PORT[s|r]");
-				success = 0;
-			} else if (so.is_ssl && ctx->ssl_ctx == NULL) {
-				mg_cry(
-				    fc(ctx),
-				    "Cannot add SSL socket, is -ssl_certificate option set?");
-				success = 0;
-			} else if ((so.sock =
-			                socket(so.lsa.sa.sa_family, SOCK_STREAM, 6)) ==
-			               INVALID_SOCKET ||
 #ifdef _WIN32
 #ifdef _WIN32
-			           /* Windows SO_REUSEADDR lets many procs binds to a
-			            * socket, SO_EXCLUSIVEADDRUSE makes the bind fail
-			            * if someone already has the socket -- DTL */
-			           setsockopt(so.sock,
-			                      SOL_SOCKET,
-			                      /* NOTE: If SO_EXCLUSIVEADDRUSE is used,
-			                       * Windows might need a few seconds before
-			                       * the same port can be used again in the
-			                       * same process, so a short Sleep may be
-			                       * required between mg_stop and mg_start.
-			                       */
-			                      SO_EXCLUSIVEADDRUSE,
-			                      (SOCK_OPT_TYPE)&on,
-			                      sizeof(on)) != 0 ||
+		/* Windows SO_REUSEADDR lets many procs binds to a
+		 * socket, SO_EXCLUSIVEADDRUSE makes the bind fail
+		 * if someone already has the socket -- DTL */
+		/* NOTE: If SO_EXCLUSIVEADDRUSE is used,
+		 * Windows might need a few seconds before
+		 * the same port can be used again in the
+		 * same process, so a short Sleep may be
+		 * required between mg_stop and mg_start.
+		 */
+		if (setsockopt(so.sock,
+		               SOL_SOCKET,
+		               SO_EXCLUSIVEADDRUSE,
+		               (SOCK_OPT_TYPE)&on,
+		               sizeof(on)) != 0) {
+			mg_cry(fc(ctx),
+			       "cannot set socket option SO_EXCLUSIVEADDRUSE (entry %i)",
+			       portsTotal);
+		}
 #else
 #else
-			           setsockopt(so.sock,
-			                      SOL_SOCKET,
-			                      SO_REUSEADDR,
-			                      (SOCK_OPT_TYPE)&on,
-			                      sizeof(on)) != 0 ||
+		if (setsockopt(so.sock,
+		               SOL_SOCKET,
+		               SO_REUSEADDR,
+		               (SOCK_OPT_TYPE)&on,
+		               sizeof(on)) != 0) {
+			mg_cry(fc(ctx),
+			       "cannot set socket option SO_REUSEADDR (entry %i)",
+			       portsTotal);
+		}
 #endif
 #endif
+
+
 #if defined(USE_IPV6)
 #if defined(USE_IPV6)
-			           (so.lsa.sa.sa_family == AF_INET6 &&
-			            setsockopt(so.sock,
-			                       IPPROTO_IPV6,
-			                       IPV6_V6ONLY,
-			                       (void *)&off,
-			                       sizeof(off)) != 0) ||
-#endif
-			           bind(so.sock,
-			                &so.lsa.sa,
-			                so.lsa.sa.sa_family == AF_INET
-			                    ? sizeof(so.lsa.sin)
-			                    : sizeof(so.lsa.sa)) != 0 ||
-			           listen(so.sock, SOMAXCONN) != 0 ||
-			           getsockname(so.sock, &(usa.sa), &len) != 0) {
-				/* TODO(mid): rewrite this IF above */
-				mg_cry(fc(ctx),
-				       "%s: cannot bind to %.*s: %d (%s)",
-				       __func__,
-				       (int)vec.len,
-				       vec.ptr,
-				       (int)ERRNO,
-				       strerror(errno));
-				if (so.sock != INVALID_SOCKET) {
-					closesocket(so.sock);
-					so.sock = INVALID_SOCKET;
-				}
-				success = 0;
-			} else if ((ptr = (struct socket *)mg_realloc(
-			                ctx->listening_sockets,
-			                (ctx->num_listening_sockets + 1) *
-			                    sizeof(ctx->listening_sockets[0]))) == NULL) {
-				closesocket(so.sock);
-				so.sock = INVALID_SOCKET;
-				success = 0;
-			} else if ((portPtr = (in_port_t *)mg_realloc(
-			                ctx->listening_ports,
-			                (ctx->num_listening_sockets + 1) *
-			                    sizeof(ctx->listening_ports[0]))) == NULL) {
-				closesocket(so.sock);
-				so.sock = INVALID_SOCKET;
-				mg_free(ptr);
-				success = 0;
-			} else {
-				set_close_on_exec(so.sock, fc(ctx));
-				ctx->listening_sockets = ptr;
-				ctx->listening_sockets[ctx->num_listening_sockets] = so;
-				ctx->listening_ports = portPtr;
-				ctx->listening_ports[ctx->num_listening_sockets] =
-				    ntohs(usa.sin.sin_port);
-				ctx->num_listening_sockets++;
-			}
+		if (so.lsa.sa.sa_family == AF_INET6 &&
+		    setsockopt(so.sock,
+		               IPPROTO_IPV6,
+		               IPV6_V6ONLY,
+		               (void *)&off,
+		               sizeof(off)) != 0) {
+			mg_cry(fc(ctx),
+			       "cannot set socket option IPV6_V6ONLY (entry %i)",
+			       portsTotal);
+		}
+#endif
+		if (bind(so.sock,
+		         &so.lsa.sa,
+		         so.lsa.sa.sa_family == AF_INET ? sizeof(so.lsa.sin)
+		                                        : sizeof(so.lsa.sa)) != 0) {
+			mg_cry(fc(ctx),
+			       "cannot bind to %.*s: %d (%s)",
+			       (int)vec.len,
+			       vec.ptr,
+			       (int)ERRNO,
+			       strerror(errno));
+			closesocket(so.sock);
+			so.sock = INVALID_SOCKET;
+			continue;
 		}
 		}
 
 
-		if (!success) {
-			close_all_listening_sockets(ctx);
+		if (listen(so.sock, SOMAXCONN) != 0) {
+			mg_cry(fc(ctx),
+			       "cannot listen to %.*s: %d (%s)",
+			       (int)vec.len,
+			       vec.ptr,
+			       (int)ERRNO,
+			       strerror(errno));
+			closesocket(so.sock);
+			so.sock = INVALID_SOCKET;
+			continue;
 		}
 		}
 
 
-		return success;
+
+		if (getsockname(so.sock, &(usa.sa), &len) != 0) {
+
+			mg_cry(fc(ctx),
+			       "call to getsockname failed %.*s: %d (%s)",
+			       (int)vec.len,
+			       vec.ptr,
+			       (int)ERRNO,
+			       strerror(errno));
+			closesocket(so.sock);
+			so.sock = INVALID_SOCKET;
+			continue;
+		}
+
+		if ((ptr = (struct socket *)mg_realloc(
+		         ctx->listening_sockets,
+		         (ctx->num_listening_sockets + 1) *
+		             sizeof(ctx->listening_sockets[0]))) == NULL) {
+
+			mg_cry(fc(ctx), "%s", "Out of memory");
+			closesocket(so.sock);
+			so.sock = INVALID_SOCKET;
+			continue;
+		}
+
+		if ((portPtr = (in_port_t *)mg_realloc(
+		         ctx->listening_ports,
+		         (ctx->num_listening_sockets + 1) *
+		             sizeof(ctx->listening_ports[0]))) == NULL) {
+
+			mg_cry(fc(ctx), "%s", "Out of memory");
+			closesocket(so.sock);
+			so.sock = INVALID_SOCKET;
+			mg_free(ptr);
+			continue;
+		}
+		set_close_on_exec(so.sock, fc(ctx));
+		ctx->listening_sockets = ptr;
+		ctx->listening_sockets[ctx->num_listening_sockets] = so;
+		ctx->listening_ports = portPtr;
+		ctx->listening_ports[ctx->num_listening_sockets] =
+		    ntohs(usa.sin.sin_port);
+		ctx->num_listening_sockets++;
+		portsOk++;
 	}
 	}
-	return 0;
+
+	if (portsOk != portsTotal) {
+		close_all_listening_sockets(ctx);
+		portsOk = 0;
+	}
+
+	return portsOk;
 }
 }
 
 
 static const char *header_val(const struct mg_connection *conn,
 static const char *header_val(const struct mg_connection *conn,