Pārlūkot izejas kodu

Added optional tag for ports in civetweb

Jeremy Friesner 1 gadu atpakaļ
vecāks
revīzija
2624754dc0
1 mainītis faili ar 42 papildinājumiem un 11 dzēšanām
  1. 42 11
      src/civetweb.c

+ 42 - 11
src/civetweb.c

@@ -1921,6 +1921,7 @@ struct socket {
 	unsigned char is_ssl;    /* Is port SSL-ed */
 	unsigned char ssl_redir; /* Is port supposed to redirect everything to SSL
 	                          * port */
+	unsigned char is_optional; /* Shouldn't cause us to exit if we can't bind to it */
 	unsigned char in_use;    /* 0: invalid, 1: valid, 2: free */
 };
 
@@ -15689,7 +15690,7 @@ parse_port_string(const struct vec *vec, struct socket *so, int *ip_version)
 	unsigned int a, b, c, d;
 	unsigned port;
 	unsigned long portUL;
-	int ch, len;
+	int len;
 	const char *cb;
 	char *endptr;
 #if defined(USE_IPV6)
@@ -15842,14 +15843,31 @@ parse_port_string(const struct vec *vec, struct socket *so, int *ip_version)
 	}
 
 	/* sscanf and the option splitting code ensure the following condition
-	 * Make sure the port is valid and vector ends with the port, 's' or 'r' */
-	if ((len > 0) && is_valid_port(port)
-	    && (((size_t)len == vec->len) || (((size_t)len + 1) == vec->len))) {
-		/* Next character after the port number */
-		ch = ((size_t)len < vec->len) ? vec->ptr[len] : '\0';
-		so->is_ssl = (ch == 's');
-		so->ssl_redir = (ch == 'r');
-		if ((ch == '\0') || (ch == 's') || (ch == 'r')) {
+	 * Make sure the port is valid and vector ends with the port, 'o', 's', or 'r' */
+	if ((len > 0) && (is_valid_port(port))) {
+		int bad_suffix = 0;
+
+		/* Parse any suffix character(s) after the port number */
+		for (size_t i=len; i<vec->len; i++)
+		{
+			unsigned char * opt = NULL;
+			switch(vec->ptr[i])
+			{
+				case 'o': opt = &so->is_optional; break;
+				case 'r': opt = &so->ssl_redir;   break;
+				case 's': opt = &so->is_ssl;      break;
+				default:  /* empty */             break;
+			}
+
+			if ((opt)&&(*opt == 0)) *opt = 1;
+			else
+			{
+				bad_suffix = 1;
+				break;
+			}
+		}
+
+		if ((bad_suffix == 0)&&((so->is_ssl == 0)||(so->ssl_redir == 0))) {
 			return 1;
 		}
 	}
@@ -15904,8 +15922,11 @@ is_ssl_port_used(const char *ports)
 		char prevIsNumber = 0;
 
 		for (i = 0; i < portslen; i++) {
-			if (prevIsNumber && (ports[i] == 's' || ports[i] == 'r')) {
-				return 1;
+			if (prevIsNumber) {
+				int suffixCharIdx = (ports[i] == 'o') ? (i+1) : i;  /* allow "os" and "or" suffixes */
+				if (ports[suffixCharIdx] == 's' || ports[suffixCharIdx] == 'r') {
+					return 1;
+				}
 			}
 			if (ports[i] >= '0' && ports[i] <= '9') {
 				prevIsNumber = 1;
@@ -16088,6 +16109,9 @@ set_ports_option(struct mg_context *phys_ctx)
 				                    strerror(errno));
 				closesocket(so.sock);
 				so.sock = INVALID_SOCKET;
+				if (so.is_optional) {
+					portsOk++; /* it's okay if we couldn't bind, this port is optional anyway */
+				}
 				continue;
 			}
 		}
@@ -16104,6 +16128,9 @@ set_ports_option(struct mg_context *phys_ctx)
 				                    strerror(errno));
 				closesocket(so.sock);
 				so.sock = INVALID_SOCKET;
+				if (so.is_optional) {
+					portsOk++; /* it's okay if we couldn't bind, this port is optional anyway */
+				}
 				continue;
 			}
 		}
@@ -16120,6 +16147,9 @@ set_ports_option(struct mg_context *phys_ctx)
 				                    strerror(errno));
 				closesocket(so.sock);
 				so.sock = INVALID_SOCKET;
+				if (so.is_optional) {
+					portsOk++; /* it's okay if we couldn't bind, this port is optional anyway */
+				}
 				continue;
 			}
 		}
@@ -20190,6 +20220,7 @@ accept_new_connection(const struct socket *listener, struct mg_context *ctx)
 		set_close_on_exec(so.sock, NULL, ctx);
 		so.is_ssl = listener->is_ssl;
 		so.ssl_redir = listener->ssl_redir;
+		so.is_optional = listener->is_optional;
 		if (getsockname(so.sock, &so.lsa.sa, &len) != 0) {
 			mg_cry_ctx_internal(ctx,
 			                    "%s: getsockname() failed: %s",