|
@@ -3203,9 +3203,16 @@ get_header(const struct mg_request_info *ri, const char *name)
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-/* Retrieve requested HTTP header multiple values, and return the number of found occurences */
|
|
|
-static int get_headers(const struct mg_request_info *ri, const char *name,
|
|
|
- const char** output, int output_max_size) {
|
|
|
+
|
|
|
+#if defined(USE_WEBSOCKET)
|
|
|
+/* Retrieve requested HTTP header multiple values, and return the number of
|
|
|
+ * found occurences */
|
|
|
+static int
|
|
|
+get_headers(const struct mg_request_info *ri,
|
|
|
+ const char *name,
|
|
|
+ const char **output,
|
|
|
+ int output_max_size)
|
|
|
+{
|
|
|
int i;
|
|
|
int cnt = 0;
|
|
|
if (ri) {
|
|
@@ -3217,6 +3224,7 @@ static int get_headers(const struct mg_request_info *ri, const char *name,
|
|
|
}
|
|
|
return cnt;
|
|
|
}
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
const char *
|
|
@@ -10533,8 +10541,11 @@ handle_websocket_request(struct mg_connection *conn,
|
|
|
/* Step 2: If a callback is responsible, call it. */
|
|
|
if (is_callback_resource) {
|
|
|
/* Step 2.1 check and select subprotocol */
|
|
|
- const char* protocols[64]; // max 64 headers
|
|
|
- int nbSubprotocolHeader = get_headers(&conn->request_info, "Sec-WebSocket-Protocol", protocols, 64);
|
|
|
+ const char *protocols[64]; // max 64 headers
|
|
|
+ int nbSubprotocolHeader = get_headers(&conn->request_info,
|
|
|
+ "Sec-WebSocket-Protocol",
|
|
|
+ protocols,
|
|
|
+ 64);
|
|
|
if (nbSubprotocolHeader > 0 && subprotocols) {
|
|
|
int cnt = 0;
|
|
|
int idx;
|
|
@@ -10550,23 +10561,26 @@ handle_websocket_request(struct mg_connection *conn,
|
|
|
do {
|
|
|
sep = strchr(protocol, ',');
|
|
|
curSubProtocol = protocol;
|
|
|
- len = sep ? (unsigned long)(sep - protocol) : strlen(protocol);
|
|
|
- while(sep && isspace(*++sep)); // ignore leading whitespaces
|
|
|
+ len = sep ? (unsigned long)(sep - protocol)
|
|
|
+ : strlen(protocol);
|
|
|
+ while (sep && isspace(*++sep))
|
|
|
+ ; // ignore leading whitespaces
|
|
|
protocol = sep;
|
|
|
|
|
|
|
|
|
for (idx = 0; idx < subprotocols->nb_subprotocols; idx++) {
|
|
|
if ((strlen(subprotocols->subprotocols[idx]) == len)
|
|
|
- && (strncmp(curSubProtocol,
|
|
|
- subprotocols->subprotocols[idx],
|
|
|
- len) == 0)) {
|
|
|
+ && (strncmp(curSubProtocol,
|
|
|
+ subprotocols->subprotocols[idx],
|
|
|
+ len) == 0)) {
|
|
|
acceptedWebSocketSubprotocol =
|
|
|
- subprotocols->subprotocols[idx];
|
|
|
+ subprotocols->subprotocols[idx];
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
} while (sep && !acceptedWebSocketSubprotocol);
|
|
|
- } while (++cnt < nbSubprotocolHeader && !acceptedWebSocketSubprotocol);
|
|
|
+ } while (++cnt < nbSubprotocolHeader
|
|
|
+ && !acceptedWebSocketSubprotocol);
|
|
|
|
|
|
conn->request_info.acceptedWebSocketSubprotocol =
|
|
|
acceptedWebSocketSubprotocol;
|
|
@@ -11899,6 +11913,7 @@ parse_port_string(const struct vec *vec, struct socket *so, int *ip_version)
|
|
|
{
|
|
|
unsigned int a, b, c, d, port;
|
|
|
int ch, len;
|
|
|
+ char *cb;
|
|
|
#if defined(USE_IPV6)
|
|
|
char buf[100] = {0};
|
|
|
#endif
|
|
@@ -11910,6 +11925,11 @@ parse_port_string(const struct vec *vec, struct socket *so, int *ip_version)
|
|
|
so->lsa.sin.sin_family = AF_INET;
|
|
|
*ip_version = 0;
|
|
|
|
|
|
+ /* Initialize port and len as invalid. */
|
|
|
+ port = 0;
|
|
|
+ len = 0;
|
|
|
+
|
|
|
+ /* Test for different ways to format this string */
|
|
|
if (sscanf(vec->ptr, "%u.%u.%u.%u:%u%n", &a, &b, &c, &d, &port, &len)
|
|
|
== 5) {
|
|
|
/* Bind to a specific IPv4 address, e.g. 192.168.1.5:8080 */
|
|
@@ -11952,10 +11972,49 @@ parse_port_string(const struct vec *vec, struct socket *so, int *ip_version)
|
|
|
so->lsa.sin.sin_port = htons((uint16_t)port);
|
|
|
*ip_version = 4;
|
|
|
|
|
|
+ } else if ((cb = strchr(vec->ptr, ':')) != NULL) {
|
|
|
+ /* Could be a hostname */
|
|
|
+ /* Will only work for RFC 952 compliant hostnames,
|
|
|
+ * starting with a letter, containing only letters,
|
|
|
+ * digits and hyphen ('-'). Newer specs may allow
|
|
|
+ * more, but this is not guaranteed here, since it
|
|
|
+ * may interfere with rules for port option lists. */
|
|
|
+ *cb = 0;
|
|
|
+ struct hostent *he = gethostbyname(vec->ptr);
|
|
|
+ *cb = ':';
|
|
|
+
|
|
|
+ if ((he != NULL) && (he->h_addrtype == AF_INET)) {
|
|
|
+ /* known IPv4 address */
|
|
|
+ *ip_version = 4;
|
|
|
+ so->lsa.sin.sin_family = AF_INET;
|
|
|
+ memcpy(&so->lsa.sin.sin_addr.s_addr, he->h_addr, 4);
|
|
|
+ if (sscanf(cb + 1, "%u%n", &port, &len) == 1) {
|
|
|
+ so->lsa.sin.sin_port = htons(port);
|
|
|
+ len += (int)(cb - vec->ptr) + 1;
|
|
|
+ } else {
|
|
|
+ port = 0;
|
|
|
+ len = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+#if defined(USE_IPV6)
|
|
|
+ } else if ((he != NULL) && (he->h_addrtype == AF_INET6)) {
|
|
|
+ /* known IPv6 address */
|
|
|
+ *ip_version = 6;
|
|
|
+ so->lsa.sin6.sin6_family = AF_INET6;
|
|
|
+ memcpy(&so->lsa.sin.sin_addr.s_addr, he->h_addr, 16);
|
|
|
+ if (sscanf(cb + 1, "%u%n", &port, &len) == 1) {
|
|
|
+ so->lsa.sin.sin_port = htons(port);
|
|
|
+ len += (int)(cb - vec->ptr) + 1;
|
|
|
+ } else {
|
|
|
+ port = 0;
|
|
|
+ len = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+#endif
|
|
|
+ }
|
|
|
+
|
|
|
} else {
|
|
|
- /* Parsing failure. Make port invalid. */
|
|
|
- port = 0;
|
|
|
- len = 0;
|
|
|
+ /* Parsing failure. */
|
|
|
}
|
|
|
|
|
|
/* sscanf and the option splitting code ensure the following condition
|