Browse Source

Merge pull request #23478 from Faless/lws_3.0.1_pr

Update libwebsocket to 3.0.1
Rémi Verschelde 6 years ago
parent
commit
60c78726a5
26 changed files with 795 additions and 637 deletions
  1. 1 3
      thirdparty/README.md
  2. 15 10
      thirdparty/libwebsockets/core/context.c
  3. 45 10
      thirdparty/libwebsockets/core/libwebsockets.c
  4. 12 0
      thirdparty/libwebsockets/core/output.c
  5. 26 7
      thirdparty/libwebsockets/core/private.h
  6. 17 27
      thirdparty/libwebsockets/libwebsockets.h
  7. 16 9
      thirdparty/libwebsockets/misc/lejp.c
  8. 9 1
      thirdparty/libwebsockets/plat/lws-plat-unix.c
  9. 20 14
      thirdparty/libwebsockets/plat/lws-plat-win.c
  10. 14 0
      thirdparty/libwebsockets/roles/h1/ops-h1.c
  11. 5 5
      thirdparty/libwebsockets/roles/http/client/client-handshake.c
  12. 25 13
      thirdparty/libwebsockets/roles/http/client/client.c
  13. 45 31
      thirdparty/libwebsockets/roles/http/header.c
  14. 1 0
      thirdparty/libwebsockets/roles/http/private.h
  15. 37 27
      thirdparty/libwebsockets/roles/http/server/lejp-conf.c
  16. 12 14
      thirdparty/libwebsockets/roles/http/server/parsers.c
  17. 40 10
      thirdparty/libwebsockets/roles/http/server/server.c
  18. 3 8
      thirdparty/libwebsockets/roles/ws/client-parser-ws.c
  19. 14 12
      thirdparty/libwebsockets/roles/ws/ops-ws.c
  20. 1 1
      thirdparty/libwebsockets/tls/mbedtls/mbedtls-server.c
  21. 0 2
      thirdparty/libwebsockets/tls/mbedtls/ssl.c
  22. 4 0
      thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_types.h
  23. 5 5
      thirdparty/libwebsockets/uwp_fixes.diff
  24. 153 153
      thirdparty/libwebsockets/win32helpers/getopt.c
  25. 240 240
      thirdparty/libwebsockets/win32helpers/getopt_long.c
  26. 35 35
      thirdparty/libwebsockets/win32helpers/gettimeofday.c

+ 1 - 3
thirdparty/README.md

@@ -264,9 +264,7 @@ File extracted from upstream source:
     - From `roles/ws` exclude `ext` folder.
   - From `tls` exclude `openssl` folder.
 - Also copy `win32helpers/` from `win32port/` inside `thirdparty/libwebsockets`
-- A small fix has been added in `libwebsockets/libwebsockets.h` to `#include <sys/socket.h>` for the BSD family.
-  This change has been PRed upstream, and should be merged before the next update. Remember to check and remove this line.
-- Another fix has been added to allow building for 32-bits UWP, replacing `GetFileSize[Ex]` and `CreateFileW` with supported functions.
+- A fix has been added to allow building for 32-bits UWP, replacing `GetFileSize[Ex]` and `CreateFileW` with supported functions.
   There is a diff for this change in `thirdparty/libwebsockets/uwp_fixes.diff`
 
 Important: `lws_config.h` and `lws_config_private.h` contains custom

+ 15 - 10
thirdparty/libwebsockets/core/context.c

@@ -134,7 +134,7 @@ lws_protocol_vh_priv_get(struct lws_vhost *vhost,
 {
 	int n = 0;
 
-	if (!vhost || !vhost->protocol_vh_privs)
+	if (!vhost || !vhost->protocol_vh_privs || !prot)
 		return NULL;
 
 	while (n < vhost->count_protocols && &vhost->protocols[n] != prot)
@@ -808,7 +808,7 @@ lws_create_vhost(struct lws_context *context,
 
 #ifdef LWS_WITH_ACCESS_LOG
 	if (info->log_filepath) {
-		vh->log_fd = open(info->log_filepath,
+		vh->log_fd = lws_open(info->log_filepath,
 				  O_CREAT | O_APPEND | O_RDWR, 0600);
 		if (vh->log_fd == (int)LWS_INVALID_FILE) {
 			lwsl_err("unable to open log filepath %s\n",
@@ -936,24 +936,29 @@ lws_create_event_pipes(struct lws_context *context)
 		wsi->tsi = n;
 		wsi->vhost = NULL;
 		wsi->event_pipe = 1;
+		wsi->desc.sockfd = LWS_SOCK_INVALID;
+		context->pt[n].pipe_wsi = wsi;
+		context->count_wsi_allocated++;
 
-		if (lws_plat_pipe_create(wsi)) {
-			lws_free(wsi);
+		if (lws_plat_pipe_create(wsi))
+			/*
+			 * platform code returns 0 if it actually created pipes
+			 * and initialized pt->dummy_pipe_fds[].  If it used
+			 * some other mechanism outside of signaling in the
+			 * normal event loop, we skip treating the pipe as
+			 * related to dummy_pipe_fds[], adding it to the fds,
+			 * etc.
+			 */
 			continue;
-		}
+
 		wsi->desc.sockfd = context->pt[n].dummy_pipe_fds[0];
 		lwsl_debug("event pipe fd %d\n", wsi->desc.sockfd);
 
-		context->pt[n].pipe_wsi = wsi;
-
 		if (context->event_loop_ops->accept)
 			context->event_loop_ops->accept(wsi);
 
 		if (__insert_wsi_socket_into_fds(context, wsi))
 			return 1;
-
-		//lws_change_pollfd(context->pt[n].pipe_wsi, 0, LWS_POLLIN);
-		context->count_wsi_allocated++;
 	}
 
 	return 0;

+ 45 - 10
thirdparty/libwebsockets/core/libwebsockets.c

@@ -28,7 +28,7 @@
 #ifdef LWS_WITH_IPV6
 #if defined(WIN32) || defined(_WIN32)
 #include <wincrypt.h>
-#include <Iphlpapi.h>
+#include <iphlpapi.h>
 #else
 #include <net/if.h>
 #endif
@@ -58,6 +58,28 @@ static const char * const log_level_names[] = {
 };
 #endif
 
+int lws_open(const char *__file, int __oflag, ...)
+{
+	va_list ap;
+	int n;
+
+	va_start(ap, __oflag);
+	if (((__oflag & O_CREAT) == O_CREAT)
+#if defined(O_TMPFILE)
+		|| ((__oflag & O_TMPFILE) == O_TMPFILE)
+#endif
+	)
+		/* last arg is really a mode_t.  But windows... */
+		n = open(__file, __oflag, va_arg(ap, uint32_t));
+	else
+		n = open(__file, __oflag);
+	va_end(ap);
+
+	lws_plat_apply_FD_CLOEXEC(n);
+
+	return n;
+}
+
 #if defined (_DEBUG)
 void lwsi_set_role(struct lws *wsi, lws_wsi_state_t role)
 {
@@ -826,7 +848,15 @@ just_kill_connection:
 		if (!wsi->protocol)
 			pro = &wsi->vhost->protocols[0];
 
-		pro->callback(wsi,
+		if (!wsi->upgraded_to_http2 || !lwsi_role_client(wsi))
+			/*
+			 * The network wsi for a client h2 connection shouldn't
+			 * call back for its role: the child stream connections
+			 * own the role.  Otherwise h2 will call back closed
+			 * one too many times as the children do it and then
+			 * the closing network stream.
+			 */
+			pro->callback(wsi,
 			      wsi->role_ops->close_cb[lwsi_role_server(wsi)],
 			      wsi->user_space, NULL, 0);
 		wsi->told_user_closed = 1;
@@ -1453,7 +1483,7 @@ lws_vfs_select_fops(const struct lws_plat_file_ops *fops, const char *vfs_path,
 		pf = fops->next;
 		while (pf) {
 			n = 0;
-			while (n < (int)ARRAY_SIZE(pf->fi) && pf->fi[n].sig) {
+			while (n < (int)LWS_ARRAY_SIZE(pf->fi) && pf->fi[n].sig) {
 				if (p >= vfs_path + pf->fi[n].len)
 					if (!strncmp(p - (pf->fi[n].len - 1),
 						    pf->fi[n].sig,
@@ -1935,9 +1965,9 @@ static const char * const colours[] = {
 	"[32;1m", /* LLL_INFO */
 	"[34;1m", /* LLL_DEBUG */
 	"[33;1m", /* LLL_PARSER */
-	"[33;1m", /* LLL_HEADER */
-	"[33;1m", /* LLL_EXT */
-	"[33;1m", /* LLL_CLIENT */
+	"[33m", /* LLL_HEADER */
+	"[33m", /* LLL_EXT */
+	"[33m", /* LLL_CLIENT */
 	"[33;1m", /* LLL_LATENCY */
 	"[30;1m", /* LLL_USER */
 };
@@ -1946,14 +1976,14 @@ LWS_VISIBLE void lwsl_emit_stderr(int level, const char *line)
 {
 	char buf[50];
 	static char tty = 3;
-	int n, m = ARRAY_SIZE(colours) - 1;
+	int n, m = LWS_ARRAY_SIZE(colours) - 1;
 
 	if (!tty)
 		tty = isatty(2) | 2;
 	lwsl_timestamp(level, buf, sizeof(buf));
 
 	if (tty == 3) {
-		n = 1 << (ARRAY_SIZE(colours) - 1);
+		n = 1 << (LWS_ARRAY_SIZE(colours) - 1);
 		while (n) {
 			if (level & n)
 				break;
@@ -2060,7 +2090,9 @@ lwsl_hexdump_level(int hexdump_level, const void *vbuf, size_t len)
 LWS_VISIBLE void
 lwsl_hexdump(const void *vbuf, size_t len)
 {
+#if defined(_DEBUG)
 	lwsl_hexdump_level(LLL_DEBUG, vbuf, len);
+#endif
 }
 
 LWS_VISIBLE int
@@ -2091,6 +2123,8 @@ lws_partial_buffered(struct lws *wsi)
 LWS_VISIBLE lws_fileofs_t
 lws_get_peer_write_allowance(struct lws *wsi)
 {
+	if (!wsi->role_ops->tx_credit)
+		return -1;
 	return wsi->role_ops->tx_credit(wsi);
 }
 
@@ -3364,7 +3398,7 @@ lws_stats_log_dump(struct lws_context *context)
 		wl = pt->http.ah_wait_list;
 		while (wl) {
 			m++;
-			wl = wl->ah_wait_list;
+			wl = wl->http.ah_wait_list;
 		}
 
 		lwsl_notice("  AH wait list count / actual:      %d / %d\n",
@@ -3401,7 +3435,8 @@ lws_stats_log_dump(struct lws_context *context)
 					strcpy(buf, "unknown");
 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
 				lwsl_notice("  peer %s: count wsi: %d, count ah: %d\n",
-					    buf, df->count_wsi, df->count_ah);
+					    buf, df->count_wsi,
+					    df->http.count_ah);
 #else
 				lwsl_notice("  peer %s: count wsi: %d\n",
 					    buf, df->count_wsi);

+ 12 - 0
thirdparty/libwebsockets/core/output.c

@@ -126,6 +126,18 @@ int lws_issue_raw(struct lws *wsi, unsigned char *buf, size_t len)
 				lwsl_info("** %p signalling to close now\n", wsi);
 				return -1; /* retry closing now */
 			}
+
+#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
+#if !defined(LWS_WITHOUT_SERVER)
+			if (wsi->http.deferred_transaction_completed) {
+				lwsl_notice("%s: partial completed, doing "
+					    "deferred transaction completed\n",
+					    __func__);
+				wsi->http.deferred_transaction_completed = 0;
+				return lws_http_transaction_completed(wsi);
+			}
+#endif
+#endif
 		}
 		/* always callback on writeable */
 		lws_callback_on_writable(wsi);

+ 26 - 7
thirdparty/libwebsockets/core/private.h

@@ -232,7 +232,7 @@
  #endif
 
 #else /* not windows */
- static inline int compatible_close(int fd) { return close(fd); }
+ static LWS_INLINE int compatible_close(int fd) { return close(fd); }
 
  #include <sys/stat.h>
  #include <sys/time.h>
@@ -351,7 +351,15 @@ extern "C" {
 
 #define LWS_H2_RX_SCRATCH_SIZE 512
 
-
+#if defined(WIN32) || defined(_WIN32)
+	 // Visual studio older than 2015 and WIN_CE has only _stricmp
+	#if (defined(_MSC_VER) && _MSC_VER < 1900) || defined(_WIN32_WCE)
+	#define strcasecmp _stricmp
+	#elif !defined(__MINGW32__)
+	#define strcasecmp stricmp
+	#endif
+	#define getdtablesize() 30000
+#endif
 
 /*
  * All lws_tls...() functions must return this type, converting the
@@ -863,6 +871,7 @@ struct lws_context {
 	unsigned int timeout_secs;
 	unsigned int pt_serv_buf_size;
 	int max_http_header_data;
+	int max_http_header_pool;
 	int simultaneous_ssl_restriction;
 	int simultaneous_ssl;
 #if defined(LWS_WITH_PEER_LIMITS)
@@ -889,7 +898,6 @@ struct lws_context {
 	volatile int service_tid;
 	int service_tid_detected;
 
-	short max_http_header_pool;
 	short count_threads;
 	short plugin_protocol_count;
 	short plugin_extension_count;
@@ -1216,7 +1224,7 @@ LWS_EXTERN int
 lws_rxflow_cache(struct lws *wsi, unsigned char *buf, int n, int len);
 
 #ifndef LWS_LATENCY
-static inline void
+static LWS_INLINE void
 lws_latency(struct lws_context *context, struct lws *wsi, const char *action,
 	    int ret, int completion) {
 	do {
@@ -1224,7 +1232,7 @@ lws_latency(struct lws_context *context, struct lws *wsi, const char *action,
 		(void)completion;
 	} while (0);
 }
-static inline void
+static LWS_INLINE void
 lws_latency_pre(struct lws_context *context, struct lws *wsi) {
 	do { (void)context; (void)wsi; } while (0);
 }
@@ -1597,6 +1605,9 @@ void lws_free(void *p);
 #define lws_free_set_NULL(P)	do { lws_realloc(P, 0, "free"); (P) = NULL; } while(0)
 #endif
 
+char *
+lws_strdup(const char *s);
+
 int
 lws_plat_pipe_create(struct lws *wsi);
 int
@@ -1606,6 +1617,9 @@ lws_plat_pipe_close(struct lws *wsi);
 int
 lws_create_event_pipes(struct lws_context *context);
 
+int lws_open(const char *__file, int __oflag, ...);
+void lws_plat_apply_FD_CLOEXEC(int n);
+
 const struct lws_plat_file_ops *
 lws_vfs_select_fops(const struct lws_plat_file_ops *fops, const char *vfs_path,
 		    const char **vpath);
@@ -1673,10 +1687,10 @@ lws_broadcast(struct lws_context *context, int reason, void *in, size_t len);
  lws_stats_atomic_max(struct lws_context * context,
 		struct lws_context_per_thread *pt, int index, uint64_t val);
 #else
- static inline uint64_t lws_stats_atomic_bump(struct lws_context * context,
+ static LWS_INLINE uint64_t lws_stats_atomic_bump(struct lws_context * context,
 		struct lws_context_per_thread *pt, int index, uint64_t bump) {
 	(void)context; (void)pt; (void)index; (void)bump; return 0; }
- static inline uint64_t lws_stats_atomic_max(struct lws_context * context,
+ static LWS_INLINE uint64_t lws_stats_atomic_max(struct lws_context * context,
 		struct lws_context_per_thread *pt, int index, uint64_t val) {
 	(void)context; (void)pt; (void)index; (void)val; return 0; }
 #endif
@@ -1703,6 +1717,11 @@ void
 lws_peer_dump_from_wsi(struct lws *wsi);
 #endif
 
+#ifdef LWS_WITH_HTTP_PROXY
+hubbub_error
+html_parser_cb(const hubbub_token *token, void *pw);
+#endif
+
 
 void
 __lws_remove_from_timeout_list(struct lws *wsi);

+ 17 - 27
thirdparty/libwebsockets/libwebsockets.h

@@ -66,14 +66,6 @@ typedef unsigned long long lws_intptr_t;
 #define O_RDONLY	_O_RDONLY
 #endif
 
-// Visual studio older than 2015 and WIN_CE has only _stricmp
-#if (defined(_MSC_VER) && _MSC_VER < 1900) || defined(_WIN32_WCE)
-#define strcasecmp _stricmp
-#elif !defined(__MINGW32__)
-#define strcasecmp stricmp
-#endif
-#define getdtablesize() 30000
-
 #define LWS_INLINE __inline
 #define LWS_VISIBLE
 #define LWS_WARN_UNUSED_RESULT
@@ -150,6 +142,7 @@ typedef unsigned long long lws_intptr_t;
 #endif
 
 #if defined(__ANDROID__)
+#include <netinet/in.h>
 #include <unistd.h>
 #define getdtablesize() sysconf(_SC_OPEN_MAX)
 #endif
@@ -164,6 +157,9 @@ typedef unsigned long long lws_intptr_t;
 #ifdef LWS_HAVE_UV_VERSION_H
 #include <uv-version.h>
 #endif
+#ifdef LWS_HAVE_NEW_UV_VERSION_H
+#include <uv/version.h>
+#endif
 #endif /* LWS_WITH_LIBUV */
 #if defined(LWS_WITH_LIBEVENT)
 #include <event2/event.h>
@@ -456,9 +452,6 @@ lwsl_visible(int level);
 #endif
 
 struct lws;
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
-#endif
 
 typedef int64_t lws_usec_t;
 
@@ -540,7 +533,7 @@ struct timer_mapping {
 
 #define lws_uv_getloop(a, b) (NULL)
 
-static inline void uv_timer_init(void *l, uv_timer_t *t)
+static LWS_INLINE void uv_timer_init(void *l, uv_timer_t *t)
 {
 	(void)l;
 	*t = NULL;
@@ -548,7 +541,7 @@ static inline void uv_timer_init(void *l, uv_timer_t *t)
 
 extern void esp32_uvtimer_cb(TimerHandle_t t);
 
-static inline void uv_timer_start(uv_timer_t *t, uv_cb_t *cb, int first, int rep)
+static LWS_INLINE void uv_timer_start(uv_timer_t *t, uv_cb_t *cb, int first, int rep)
 {
 	struct timer_mapping *tm = (struct timer_mapping *)malloc(sizeof(*tm));
 
@@ -563,12 +556,12 @@ static inline void uv_timer_start(uv_timer_t *t, uv_cb_t *cb, int first, int rep
 	xTimerStart(*t, 0);
 }
 
-static inline void uv_timer_stop(uv_timer_t *t)
+static LWS_INLINE void uv_timer_stop(uv_timer_t *t)
 {
 	xTimerStop(*t, 0);
 }
 
-static inline void uv_close(uv_handle_t *h, void *v)
+static LWS_INLINE void uv_close(uv_handle_t *h, void *v)
 {
 	free(pvTimerGetTimerID((uv_timer_t)h));
 	xTimerDelete(*(uv_timer_t *)h, 0);
@@ -1757,7 +1750,7 @@ lws_genhash_destroy(struct lws_genhash_ctx *ctx, void *result);
  * If the return is nonzero, it failed and there is nothing needing to be
  * destroyed.
  */
-int
+LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
 lws_genhmac_init(struct lws_genhmac_ctx *ctx, enum lws_genhmac_types type,
 		const uint8_t *key, size_t key_len);
 
@@ -1771,7 +1764,7 @@ lws_genhmac_init(struct lws_genhmac_ctx *ctx, enum lws_genhmac_types type,
  *
  * If the return is nonzero, it failed and needs destroying.
  */
-int
+LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
 lws_genhmac_update(struct lws_genhmac_ctx *ctx, const void *in, size_t len);
 
 /** lws_genhmac_destroy() - copy out the result digest and destroy the ctx
@@ -1785,7 +1778,7 @@ lws_genhmac_update(struct lws_genhmac_ctx *ctx, const void *in, size_t len);
  * NULL result is supported so that you can destroy the ctx cleanly on error
  * conditions, where there is no valid result.
  */
-int
+LWS_VISIBLE LWS_EXTERN int
 lws_genhmac_destroy(struct lws_genhmac_ctx *ctx, void *result);
 ///@}
 
@@ -2812,7 +2805,7 @@ struct lws_context_creation_info {
 	/**< VHOST: pointer to optional linked list of per-vhost
 	 * options made accessible to protocols */
 	int keepalive_timeout;
-	/**< VHOST: (default = 0 = 60s) seconds to allow remote
+	/**< VHOST: (default = 0 = 5s) seconds to allow remote
 	 * client to hold on to an idle HTTP/1.1 connection */
 	const char *log_filepath;
 	/**< VHOST: filepath to append logs to... this is opened before
@@ -4943,7 +4936,7 @@ lws_write(struct lws *wsi, unsigned char *buf, size_t len,
 	lws_write(wsi, (unsigned char *)(buf), len, LWS_WRITE_HTTP)
 
 /* helper for multi-frame ws message flags */
-static inline int
+static LWS_INLINE int
 lws_write_ws_flags(int initial, int is_start, int is_end)
 {
 	int r;
@@ -5621,13 +5614,13 @@ struct lws_dll_lws { /* typed as struct lws * */
 
 #define lws_dll_is_null(___dll) (!(___dll)->prev && !(___dll)->next)
 
-static inline void
+static LWS_INLINE void
 lws_dll_lws_add_front(struct lws_dll_lws *_a, struct lws_dll_lws *_head)
 {
 	lws_dll_add_front((struct lws_dll *)_a, (struct lws_dll *)_head);
 }
 
-static inline void
+static LWS_INLINE void
 lws_dll_lws_remove(struct lws_dll_lws *_a)
 {
 	lws_dll_remove((struct lws_dll *)_a);
@@ -7064,9 +7057,6 @@ lws_email_destroy(struct lws_email *email);
 //@{
 struct lejp_ctx;
 
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(_x) (sizeof(_x) / sizeof(_x[0]))
-#endif
 #define LWS_ARRAY_SIZE(_x) (sizeof(_x) / sizeof(_x[0]))
 #define LEJP_FLAG_WS_KEEP 64
 #define LEJP_FLAG_WS_COMMENTLINE 32
@@ -7219,7 +7209,7 @@ typedef signed char (*lejp_callback)(struct lejp_ctx *ctx, char reason);
 #endif
 #ifndef LEJP_STRING_CHUNK
 /* must be >= 30 to assemble floats */
-#define LEJP_STRING_CHUNK 255
+#define LEJP_STRING_CHUNK 254
 #endif
 
 enum num_flags {
@@ -7253,7 +7243,7 @@ struct lejp_ctx {
 	uint16_t i[LEJP_MAX_INDEX_DEPTH]; /* index array */
 	uint16_t wild[LEJP_MAX_INDEX_DEPTH]; /* index array */
 	char path[LEJP_MAX_PATH];
-	char buf[LEJP_STRING_CHUNK];
+	char buf[LEJP_STRING_CHUNK + 1];
 
 	/* int */
 

+ 16 - 9
thirdparty/libwebsockets/misc/lejp.c

@@ -20,6 +20,7 @@
  */
 
 #include <libwebsockets.h>
+#include "core/private.h"
 #include <string.h>
 #include <stdio.h>
 
@@ -30,7 +31,7 @@
  * \param callback:	your user callback which will received parsed tokens
  * \param user:	optional user data pointer untouched by lejp
  * \param paths:	your array of name elements you are interested in
- * \param count_paths:	ARRAY_SIZE() of @paths
+ * \param count_paths:	LWS_ARRAY_SIZE() of @paths
  *
  * Prepares your context struct for use with lejp
  */
@@ -250,7 +251,7 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len)
 
 		case LEJP_MP_STRING:
 			if (c == '\"') {
-				if (!ctx->sp) {
+				if (!ctx->sp) { /* JSON can't end on quote */
 					ret = LEJP_REJECT_MP_STRING_UNDERRUN;
 					goto reject;
 				}
@@ -417,7 +418,7 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len)
 					goto reject;
 				}
 				ctx->i[ctx->ipos++] = 0;
-				if (ctx->ipos > ARRAY_SIZE(ctx->i)) {
+				if (ctx->ipos > LWS_ARRAY_SIZE(ctx->i)) {
 					ret = LEJP_REJECT_MP_DELIM_ISTACK;
 					goto reject;
 				}
@@ -425,17 +426,23 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len)
 
 			case ']':
 				/* pop */
+				if (!ctx->sp) { /* JSON can't end on ] */
+					ret = LEJP_REJECT_MP_C_OR_E_UNDERF;
+					goto reject;
+				}
 				ctx->sp--;
 				if (ctx->st[ctx->sp].s != LEJP_MP_ARRAY_END) {
 					ret = LEJP_REJECT_MP_C_OR_E_NOTARRAY;
 					goto reject;
 				}
 				/* drop the path [n] bit */
-				ctx->ppos = ctx->st[ctx->sp - 1].p;
-				ctx->ipos = ctx->st[ctx->sp - 1].i;
+				if (ctx->sp) {
+					ctx->ppos = ctx->st[ctx->sp - 1].p;
+					ctx->ipos = ctx->st[ctx->sp - 1].i;
+				}
 				ctx->path[ctx->ppos] = '\0';
 				if (ctx->path_match &&
-					       ctx->ppos <= ctx->path_match_len)
+				    ctx->ppos <= ctx->path_match_len)
 					/*
 					 * we shrank the path to be
 					 * smaller than the matching point
@@ -603,7 +610,7 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len)
 				break;
 			}
 			if (c == ']') {
-				if (!ctx->sp) {
+				if (!ctx->sp) {  /* JSON can't end on ] */
 					ret = LEJP_REJECT_MP_C_OR_E_UNDERF;
 					goto reject;
 				}
@@ -631,7 +638,7 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len)
 				goto redo_character;
 			}
 			if (c == '}') {
-				if (ctx->sp == 0) {
+				if (!ctx->sp) {
 					lejp_check_path_match(ctx);
 					if (ctx->callback(ctx, LEJPCB_OBJECT_END)) {
 						ret = LEJP_REJECT_CALLBACK;
@@ -716,7 +723,7 @@ add_stack_level:
 
 		ctx->st[ctx->sp].p = ctx->ppos;
 		ctx->st[ctx->sp].i = ctx->ipos;
-		if (++ctx->sp == ARRAY_SIZE(ctx->st)) {
+		if (++ctx->sp == LWS_ARRAY_SIZE(ctx->st)) {
 			ret = LEJP_REJECT_STACK_OVERFLOW;
 			goto reject;
 		}

+ 9 - 1
thirdparty/libwebsockets/plat/lws-plat-unix.c

@@ -30,6 +30,12 @@
 #endif
 #include <dirent.h>
 
+void lws_plat_apply_FD_CLOEXEC(int n)
+{
+	if (n != -1)
+		fcntl(n, F_SETFD, FD_CLOEXEC );
+}
+
 int
 lws_plat_socket_offset(void)
 {
@@ -330,6 +336,8 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, int fd)
 	struct protoent *tcp_proto;
 #endif
 
+	fcntl(fd, F_SETFD, FD_CLOEXEC);
+
 	if (vhost->ka_time) {
 		/* enable keepalive on this socket */
 		optval = 1;
@@ -952,7 +960,7 @@ lws_plat_write_file(const char *filename, void *buf, int len)
 LWS_VISIBLE int
 lws_plat_read_file(const char *filename, void *buf, int len)
 {
-	int n, fd = open(filename, O_RDONLY);
+	int n, fd = lws_open(filename, O_RDONLY);
 	if (fd == -1)
 		return -1;
 

+ 20 - 14
thirdparty/libwebsockets/plat/lws-plat-win.c

@@ -3,6 +3,10 @@
 #endif
 #include "core/private.h"
 
+void lws_plat_apply_FD_CLOEXEC(int n)
+{
+}
+
 int
 lws_plat_socket_offset(void)
 {
@@ -54,7 +58,7 @@ time_in_microseconds()
 	memcpy(&datetime, &filetime, sizeof(datetime));
 
 	/* Windows file times are in 100s of nanoseconds. */
-	return (datetime.QuadPart - DELTA_EPOCH_IN_MICROSECS) / 10;
+	return (datetime.QuadPart / 10) - DELTA_EPOCH_IN_MICROSECS;
 }
 
 #ifdef _WIN32_WCE
@@ -229,23 +233,21 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
 			continue;
 
 		wsi = wsi_from_fd(context, pfd->fd);
-		if (wsi->listener)
+		if (!wsi || wsi->listener)
 			continue;
-		if (!wsi || wsi->sock_send_blocking)
+		if (wsi->sock_send_blocking)
 			continue;
 		pfd->revents = LWS_POLLOUT;
 		n = lws_service_fd(context, pfd);
 		if (n < 0)
 			return -1;
+
+		/* Force WSAWaitForMultipleEvents() to check events and then return immediately. */
+		timeout_ms = 0;
+
 		/* if something closed, retry this slot */
 		if (n)
 			i--;
-
-		/*
-		 * any wsi has truncated, force him signalled
-		 */
-		if (wsi->trunc_len)
-			WSASetEvent(pt->events[0]);
 	}
 
 	/*
@@ -261,9 +263,11 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
 	}
 
 	if (timeout_ms) {
+		lws_usec_t t;
+
 		lws_pt_lock(pt, __func__);
 		/* don't stay in poll wait longer than next hr timeout */
-		lws_usec_t t =  __lws_hrtimer_service(pt);
+		t =  __lws_hrtimer_service(pt);
 
 		if ((lws_usec_t)timeout_ms * 1000 > t)
 			timeout_ms = (int)(t / 1000);
@@ -310,8 +314,10 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
 			if (pfd->revents & LWS_POLLHUP)
 				--eIdx;
 
-			if (pfd->revents)
+			if (pfd->revents) {
+				recv(pfd->fd, NULL, 0, 0);
 				lws_service_fd_tsi(context, pfd, tsi);
+			}
 		}
 	}
 
@@ -637,7 +643,7 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
 	lws_fop_fd_t fop_fd;
 	FILE_STANDARD_INFO fInfo = {0};
 
-	MultiByteToWideChar(CP_UTF8, 0, filename, -1, buf, ARRAY_SIZE(buf));
+	MultiByteToWideChar(CP_UTF8, 0, filename, -1, buf, LWS_ARRAY_SIZE(buf));
 
 #if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0602 // Windows 8 (minimum when UWP_ENABLED, but can be used in Windows builds)
 	CREATEFILE2_EXTENDED_PARAMETERS extParams = {0};
@@ -810,7 +816,7 @@ lws_plat_write_file(const char *filename, void *buf, int len)
 {
 	int m, fd;
 
-	fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+	fd = lws_open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
 
 	if (fd == -1)
 		return -1;
@@ -824,7 +830,7 @@ lws_plat_write_file(const char *filename, void *buf, int len)
 LWS_VISIBLE int
 lws_plat_read_file(const char *filename, void *buf, int len)
 {
-	int n, fd = open(filename, O_RDONLY);
+	int n, fd = lws_open(filename, O_RDONLY);
 	if (fd == -1)
 		return -1;
 

+ 14 - 0
thirdparty/libwebsockets/roles/h1/ops-h1.c

@@ -195,6 +195,7 @@ postbody_completion:
 		}
 		break;
 
+	case LRS_RETURNED_CLOSE:
 	case LRS_AWAITING_CLOSE_ACK:
 	case LRS_WAITING_TO_SEND_CLOSE:
 	case LRS_SHUTDOWN:
@@ -444,6 +445,16 @@ try_pollout:
 
 	if (lwsi_state(wsi) != LRS_ISSUING_FILE) {
 
+		if (wsi->trunc_len) {
+			//lwsl_notice("%s: completing partial\n", __func__);
+			if (lws_issue_raw(wsi, wsi->trunc_alloc + wsi->trunc_offset,
+					  wsi->trunc_len) < 0) {
+				lwsl_info("%s signalling to close\n", __func__);
+				goto fail;
+			}
+			return LWS_HPI_RET_HANDLED;
+		}
+
 		lws_stats_atomic_bump(wsi->context, pt,
 					LWSSTATS_C_WRITEABLE_CB, 1);
 #if defined(LWS_WITH_STATS)
@@ -655,6 +666,9 @@ rops_destroy_role_h1(struct lws *wsi)
 		ah = ah->next;
 	}
 
+#ifdef LWS_ROLE_WS
+	lws_free_set_NULL(wsi->ws);
+#endif
 	return 0;
 }
 

+ 5 - 5
thirdparty/libwebsockets/roles/http/client/client-handshake.c

@@ -162,7 +162,7 @@ create_new_conn:
 
 	if (!wsi->client_hostname_copy)
 		wsi->client_hostname_copy =
-			strdup(lws_hdr_simple_ptr(wsi,
+			lws_strdup(lws_hdr_simple_ptr(wsi,
 					_WSI_TOKEN_CLIENT_PEER_ADDRESS));
 
 	/*
@@ -654,13 +654,13 @@ lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port,
 	lws_ssl_close(wsi);
 #endif
 
+	__remove_wsi_socket_from_fds(wsi);
+
 	if (wsi->context->event_loop_ops->close_handle_manually)
 		wsi->context->event_loop_ops->close_handle_manually(wsi);
 	else
 		compatible_close(wsi->desc.sockfd);
 
-	__remove_wsi_socket_from_fds(wsi);
-
 #if defined(LWS_WITH_TLS)
 	wsi->tls.use_ssl = ssl;
 #else
@@ -717,7 +717,7 @@ lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port,
 }
 
 #ifdef LWS_WITH_HTTP_PROXY
-static hubbub_error
+hubbub_error
 html_parser_cb(const hubbub_token *token, void *pw)
 {
 	struct lws_rewrite *r = (struct lws_rewrite *)pw;
@@ -846,7 +846,7 @@ html_parser_cb(const hubbub_token *token, void *pw)
 
 #endif
 
-static char *
+char *
 lws_strdup(const char *s)
 {
 	char *d = lws_malloc(strlen(s) + 1, "strdup");

+ 25 - 13
thirdparty/libwebsockets/roles/http/client/client.c

@@ -93,7 +93,7 @@ lws_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd,
 	char *sb = p;
 	int n = 0;
 #if defined(LWS_WITH_SOCKS5)
-	char conn_mode = 0, pending_timeout = 0;
+	int conn_mode = 0, pending_timeout = 0;
 #endif
 
 	if ((pollfd->revents & LWS_POLLOUT) &&
@@ -252,6 +252,8 @@ socks_reply_fail:
 			/* clear his proxy connection timeout */
 			lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
 			goto start_ws_handshake;
+		default:
+			break;
 		}
 		break;
 #endif
@@ -578,6 +580,8 @@ lws_http_transaction_completed_client(struct lws *wsi)
 			"queued client done");
 	}
 
+	_lws_header_table_reset(wsi->http.ah);
+
 	/* after the first one, they can only be coming from the queue */
 	wsi->transaction_from_pipeline_queue = 1;
 
@@ -629,12 +633,20 @@ lws_http_transaction_completed_client(struct lws *wsi)
 }
 
 LWS_VISIBLE LWS_EXTERN unsigned int
-lws_http_client_http_response(struct lws *wsi)
+lws_http_client_http_response(struct lws *_wsi)
 {
-	if (!wsi->http.ah)
-		return 0;
+	struct lws *wsi;
+	unsigned int resp;
+
+	if (_wsi->http.ah && _wsi->http.ah->http_response)
+		return _wsi->http.ah->http_response;
 
-	return wsi->http.ah->http_response;
+	lws_vhost_lock(_wsi->vhost);
+	wsi = _lws_client_wsi_master(_wsi);
+	resp = wsi->http.ah->http_response;
+	lws_vhost_unlock(_wsi->vhost);
+
+	return resp;
 }
 #endif
 #if defined(LWS_PLAT_OPTEE)
@@ -781,7 +793,7 @@ lws_client_interpret_server_handshake(struct lws *wsi)
 			q = strrchr(new_path, '/');
 			if (q)
 				lws_strncpy(q + 1, p, sizeof(new_path) -
-							(q - new_path));
+							(q - new_path) - 1);
 			else
 				path = p;
 		}
@@ -910,9 +922,9 @@ lws_client_interpret_server_handshake(struct lws *wsi)
 		 * we seem to be good to go, give client last chance to check
 		 * headers and OK it
 		 */
-		if (wsi->protocol->callback(wsi,
+		if (w->protocol->callback(w,
 				LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH,
-					    wsi->user_space, NULL, 0)) {
+					    w->user_space, NULL, 0)) {
 
 			cce = "HS: disallowed by client filter";
 			goto bail2;
@@ -924,9 +936,9 @@ lws_client_interpret_server_handshake(struct lws *wsi)
 		wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
 
 		/* call him back to inform him he is up */
-		if (wsi->protocol->callback(wsi,
+		if (w->protocol->callback(w,
 					    LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP,
-					    wsi->user_space, NULL, 0)) {
+					    w->user_space, NULL, 0)) {
 			cce = "HS: disallowed at ESTABLISHED";
 			goto bail3;
 		}
@@ -964,9 +976,9 @@ bail2:
 		n = 0;
 		if (cce)
 			n = (int)strlen(cce);
-		wsi->protocol->callback(wsi,
+		w->protocol->callback(w,
 				LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
-				wsi->user_space, (void *)cce,
+				w->user_space, (void *)cce,
 				(unsigned int)n);
 	}
 	wsi->already_did_cce = 1;
@@ -1228,4 +1240,4 @@ completed:
 	return 0;
 }
 
-#endif
+#endif

+ 45 - 31
thirdparty/libwebsockets/roles/http/header.c

@@ -26,7 +26,7 @@
 const unsigned char *
 lws_token_to_string(enum lws_token_indexes token)
 {
-	if ((unsigned int)token >= ARRAY_SIZE(set))
+	if ((unsigned int)token >= LWS_ARRAY_SIZE(set))
 		return NULL;
 
 	return (unsigned char *)set[token];
@@ -149,9 +149,17 @@ lws_add_http_common_headers(struct lws *wsi, unsigned int code,
 		    			(int)strlen(content_type), p, end))
 		return 1;
 
-	if (content_len != LWS_ILLEGAL_HTTP_CONTENT_LEN &&
-	    lws_add_http_header_content_length(wsi, content_len, p, end))
-		return 1;
+	if (content_len != LWS_ILLEGAL_HTTP_CONTENT_LEN) {
+		if (lws_add_http_header_content_length(wsi, content_len, p, end))
+			return 1;
+	} else {
+		if (lws_add_http_header_by_token(wsi, WSI_TOKEN_CONNECTION,
+						 (unsigned char *)"close", 5,
+						 p, end))
+			return 1;
+
+		wsi->http.connection_type = HTTP_CONNECTION_CLOSE;
+	}
 
 	return 0;
 }
@@ -204,34 +212,40 @@ lws_add_http_header_status(struct lws *wsi, unsigned int _code,
 #endif
 
 #ifdef LWS_WITH_HTTP2
-	if (lwsi_role_h2(wsi) || lwsi_role_h2_ENCAPSULATION(wsi))
-		return lws_add_http2_header_status(wsi, code, p, end);
+	if (lwsi_role_h2(wsi) || lwsi_role_h2_ENCAPSULATION(wsi)) {
+		n = lws_add_http2_header_status(wsi, code, p, end);
+		if (n)
+			return n;
+	} else
 #endif
-	if (code >= 400 && code < (400 + ARRAY_SIZE(err400)))
-		description = err400[code - 400];
-	if (code >= 500 && code < (500 + ARRAY_SIZE(err500)))
-		description = err500[code - 500];
-
-	if (code == 100)
-		description = "Continue";
-	if (code == 200)
-		description = "OK";
-	if (code == 304)
-		description = "Not Modified";
-	else
-		if (code >= 300 && code < 400)
-			description = "Redirect";
-
-	if (wsi->http.request_version < ARRAY_SIZE(hver))
-		p1 = hver[wsi->http.request_version];
-	else
-		p1 = hver[0];
-
-	n = sprintf((char *)code_and_desc, "%s %u %s", p1, code, description);
-
-	if (lws_add_http_header_by_name(wsi, NULL, code_and_desc, n, p, end))
-		return 1;
-
+	{
+		if (code >= 400 && code < (400 + LWS_ARRAY_SIZE(err400)))
+			description = err400[code - 400];
+		if (code >= 500 && code < (500 + LWS_ARRAY_SIZE(err500)))
+			description = err500[code - 500];
+
+		if (code == 100)
+			description = "Continue";
+		if (code == 200)
+			description = "OK";
+		if (code == 304)
+			description = "Not Modified";
+		else
+			if (code >= 300 && code < 400)
+				description = "Redirect";
+
+		if (wsi->http.request_version < LWS_ARRAY_SIZE(hver))
+			p1 = hver[wsi->http.request_version];
+		else
+			p1 = hver[0];
+
+		n = sprintf((char *)code_and_desc, "%s %u %s", p1, code,
+			    description);
+
+		if (lws_add_http_header_by_name(wsi, NULL, code_and_desc, n, p,
+						end))
+			return 1;
+	}
 	headers = wsi->vhost->headers;
 	while (headers) {
 		if (lws_add_http_header_by_name(wsi,

+ 1 - 0
thirdparty/libwebsockets/roles/http/private.h

@@ -227,6 +227,7 @@ struct _lws_http_mode_related {
 #if defined(LWS_WITH_HTTP_PROXY)
 	unsigned int perform_rewrite:1;
 #endif
+	unsigned int deferred_transaction_completed:1;
 };
 
 

+ 37 - 27
thirdparty/libwebsockets/roles/http/server/lejp-conf.c

@@ -205,6 +205,7 @@ struct jpargs {
 	unsigned int enable_client_ssl:1;
 	unsigned int fresh_mount:1;
 	unsigned int any_vhosts:1;
+	unsigned int chunk:1;
 };
 
 static void *
@@ -213,6 +214,8 @@ lwsws_align(struct jpargs *a)
 	if ((lws_intptr_t)(a->p) & 15)
 		a->p += 16 - ((lws_intptr_t)(a->p) & 15);
 
+	a->chunk = 0;
+
 	return a->p;
 }
 
@@ -225,7 +228,7 @@ arg_to_bool(const char *s)
 	if (n)
 		return 1;
 
-	for (n = 0; n < (int)ARRAY_SIZE(on); n++)
+	for (n = 0; n < (int)LWS_ARRAY_SIZE(on); n++)
 		if (!strcasecmp(s, on[n]))
 			return 1;
 
@@ -413,25 +416,30 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
 	}
 
 	/* this catches, eg, vhosts[].headers[].xxx */
-	if (reason == LEJPCB_VAL_STR_END &&
+	if ((reason == LEJPCB_VAL_STR_END || reason == LEJPCB_VAL_STR_CHUNK) &&
 	    ctx->path_match == LEJPVP_HEADERS_NAME + 1) {
-		headers = lwsws_align(a);
-		a->p += sizeof(*headers);
-
-		n = lejp_get_wildcard(ctx, 0, a->p, a->end - a->p);
-		/* ie, enable this protocol, no options yet */
-		headers->next = a->info->headers;
-		a->info->headers = headers;
-		headers->name = a->p;
-		// lwsl_notice("  adding header %s=%s\n", a->p, ctx->buf);
-		a->p += n - 1;
-		*(a->p++) = ':';
-		if (a->p < a->end)
-			*(a->p++) = '\0';
-		else
-			*(a->p - 1) = '\0';
-		headers->value = a->p;
-		headers->options = NULL;
+		if (!a->chunk) {
+			headers = lwsws_align(a);
+			a->p += sizeof(*headers);
+
+			n = lejp_get_wildcard(ctx, 0, a->p,
+					lws_ptr_diff(a->end, a->p));
+			/* ie, add this header */
+			headers->next = a->info->headers;
+			a->info->headers = headers;
+			headers->name = a->p;
+
+			lwsl_notice("  adding header %s=%s\n", a->p, ctx->buf);
+			a->p += n - 1;
+			*(a->p++) = ':';
+			if (a->p < a->end)
+				*(a->p++) = '\0';
+			else
+				*(a->p - 1) = '\0';
+			headers->value = a->p;
+			headers->options = NULL;
+		}
+		a->chunk = reason == LEJPCB_VAL_STR_CHUNK;
 		goto dostring;
 	}
 
@@ -502,7 +510,7 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
 		if (a->last)
 			a->last->mount_next = m;
 
-		for (n = 0; n < (int)ARRAY_SIZE(mount_protocols); n++)
+		for (n = 0; n < (int)LWS_ARRAY_SIZE(mount_protocols); n++)
 			if (!strncmp(a->m.origin, mount_protocols[n],
 			     strlen(mount_protocols[n]))) {
 				lwsl_info("----%s\n", a->m.origin);
@@ -512,7 +520,7 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
 				break;
 			}
 
-		if (n == (int)ARRAY_SIZE(mount_protocols)) {
+		if (n == (int)LWS_ARRAY_SIZE(mount_protocols)) {
 			lwsl_err("unsupported protocol:// %s\n", a->m.origin);
 			return 1;
 		}
@@ -750,6 +758,7 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
 
 dostring:
 	p = ctx->buf;
+	p[LEJP_STRING_CHUNK] = '\0';
 	p1 = strstr(p, ESC_INSTALL_DATADIR);
 	if (p1) {
 		n = p1 - p;
@@ -762,7 +771,8 @@ dostring:
 	}
 
 	a->p += lws_snprintf(a->p, a->end - a->p, "%s", p);
-	*(a->p)++ = '\0';
+	if (reason == LEJPCB_VAL_STR_END)
+		*(a->p)++ = '\0';
 
 	return 0;
 }
@@ -779,7 +789,7 @@ lwsws_get_config(void *user, const char *f, const char * const *paths,
 	struct lejp_ctx ctx;
 	int n, m, fd;
 
-	fd = open(f, O_RDONLY);
+	fd = lws_open(f, O_RDONLY);
 	if (fd < 0) {
 		lwsl_err("Cannot open %s\n", f);
 		return 2;
@@ -927,11 +937,11 @@ lwsws_get_config_globals(struct lws_context_creation_info *info, const char *d,
 
 	lws_snprintf(dd, sizeof(dd) - 1, "%s/conf", d);
 	if (lwsws_get_config(&a, dd, paths_global,
-			     ARRAY_SIZE(paths_global), lejp_globals_cb) > 1)
+			     LWS_ARRAY_SIZE(paths_global), lejp_globals_cb) > 1)
 		return 1;
 	lws_snprintf(dd, sizeof(dd) - 1, "%s/conf.d", d);
 	if (lwsws_get_config_d(&a, dd, paths_global,
-			       ARRAY_SIZE(paths_global), lejp_globals_cb) > 1)
+			       LWS_ARRAY_SIZE(paths_global), lejp_globals_cb) > 1)
 		return 1;
 
 	a.plugin_dirs[a.count_plugin_dirs] = NULL;
@@ -962,11 +972,11 @@ lwsws_get_config_vhosts(struct lws_context *context,
 
 	lws_snprintf(dd, sizeof(dd) - 1, "%s/conf", d);
 	if (lwsws_get_config(&a, dd, paths_vhosts,
-			     ARRAY_SIZE(paths_vhosts), lejp_vhosts_cb) > 1)
+			     LWS_ARRAY_SIZE(paths_vhosts), lejp_vhosts_cb) > 1)
 		return 1;
 	lws_snprintf(dd, sizeof(dd) - 1, "%s/conf.d", d);
 	if (lwsws_get_config_d(&a, dd, paths_vhosts,
-			       ARRAY_SIZE(paths_vhosts), lejp_vhosts_cb) > 1)
+			       LWS_ARRAY_SIZE(paths_vhosts), lejp_vhosts_cb) > 1)
 		return 1;
 
 	*cs = a.p;

+ 12 - 14
thirdparty/libwebsockets/roles/http/server/parsers.c

@@ -563,7 +563,7 @@ int LWS_WARN_UNUSED_RESULT
 lws_hdr_simple_create(struct lws *wsi, enum lws_token_indexes h, const char *s)
 {
 	wsi->http.ah->nfrag++;
-	if (wsi->http.ah->nfrag == ARRAY_SIZE(wsi->http.ah->frags)) {
+	if (wsi->http.ah->nfrag == LWS_ARRAY_SIZE(wsi->http.ah->frags)) {
 		lwsl_warn("More hdr frags than we can deal with, dropping\n");
 		return -1;
 	}
@@ -677,18 +677,16 @@ lws_parse_urldecode(struct lws *wsi, uint8_t *_c)
 			return -1;
 		/* genuine delimiter */
 		if ((c == '&' || c == ';') && !enc) {
-			if (issue_char(wsi, c) < 0)
+			if (issue_char(wsi, '\0') < 0)
 				return -1;
-			/* swallow the terminator */
-			ah->frags[ah->nfrag].len--;
 			/* link to next fragment */
 			ah->frags[ah->nfrag].nfrag = ah->nfrag + 1;
 			ah->nfrag++;
-			if (ah->nfrag >= ARRAY_SIZE(ah->frags))
+			if (ah->nfrag >= LWS_ARRAY_SIZE(ah->frags))
 				goto excessive;
 			/* start next fragment after the & */
 			ah->post_literal_equal = 0;
-			ah->frags[ah->nfrag].offset = ah->pos;
+			ah->frags[ah->nfrag].offset = ++ah->pos;
 			ah->frags[ah->nfrag].len = 0;
 			ah->frags[ah->nfrag].nfrag = 0;
 			goto swallow;
@@ -787,9 +785,9 @@ lws_parse_urldecode(struct lws *wsi, uint8_t *_c)
 
 		/* move to using WSI_TOKEN_HTTP_URI_ARGS */
 		ah->nfrag++;
-		if (ah->nfrag >= ARRAY_SIZE(ah->frags))
+		if (ah->nfrag >= LWS_ARRAY_SIZE(ah->frags))
 			goto excessive;
-		ah->frags[ah->nfrag].offset = ah->pos;
+		ah->frags[ah->nfrag].offset = ++ah->pos;
 		ah->frags[ah->nfrag].len = 0;
 		ah->frags[ah->nfrag].nfrag = 0;
 
@@ -852,10 +850,10 @@ lws_parse(struct lws *wsi, unsigned char *buf, int *len)
 			    c == ' ')
 				break;
 
-			for (m = 0; m < ARRAY_SIZE(methods); m++)
+			for (m = 0; m < LWS_ARRAY_SIZE(methods); m++)
 				if (ah->parser_state == methods[m])
 					break;
-			if (m == ARRAY_SIZE(methods))
+			if (m == LWS_ARRAY_SIZE(methods))
 				/* it was not any of the methods */
 				goto check_eol;
 
@@ -983,7 +981,7 @@ nope:
 			if (ah->lextable_pos < 0 && lwsi_role_h1(wsi) &&
 			    lwsi_role_server(wsi)) {
 				/* this is not a header we know about */
-				for (m = 0; m < ARRAY_SIZE(methods); m++)
+				for (m = 0; m < LWS_ARRAY_SIZE(methods); m++)
 					if (ah->frag_index[methods[m]]) {
 						/*
 						 * already had the method, no idea what
@@ -996,7 +994,7 @@ nope:
 				 * hm it's an unknown http method from a client in fact,
 				 * it cannot be valid http
 				 */
-				if (m == ARRAY_SIZE(methods)) {
+				if (m == LWS_ARRAY_SIZE(methods)) {
 					/*
 					 * are we set up to accept raw in these cases?
 					 */
@@ -1025,7 +1023,7 @@ nope:
 						lextable[ah->lextable_pos + 1];
 
 				lwsl_parser("known hdr %d\n", n);
-				for (m = 0; m < ARRAY_SIZE(methods); m++)
+				for (m = 0; m < LWS_ARRAY_SIZE(methods); m++)
 					if (n == methods[m] &&
 					    ah->frag_index[methods[m]]) {
 						lwsl_warn("Duplicated method\n");
@@ -1061,7 +1059,7 @@ nope:
 start_fragment:
 			ah->nfrag++;
 excessive:
-			if (ah->nfrag == ARRAY_SIZE(ah->frags)) {
+			if (ah->nfrag == LWS_ARRAY_SIZE(ah->frags)) {
 				lwsl_warn("More hdr frags than we can deal with\n");
 				return -1;
 			}

+ 40 - 10
thirdparty/libwebsockets/roles/http/server/server.c

@@ -131,6 +131,17 @@ done_list:
 
 	(void)n;
 #if defined(__linux__)
+#ifdef LWS_WITH_UNIX_SOCK
+	/*
+	 * A Unix domain sockets cannot be bound for several times, even if we set
+	 * the SO_REUSE* options on.
+	 * However, fortunately, each thread is able to independently listen when
+	 * running on a reasonably new Linux kernel. So we can safely assume
+	 * creating just one listening socket for a multi-threaded environment won't
+	 * fail in most cases.
+	 */
+	if (!LWS_UNIX_SOCK_ENABLED(vhost))
+#endif
 	limit = vhost->context->count_threads;
 #endif
 
@@ -694,7 +705,7 @@ lws_find_string_in_file(const char *filename, const char *string, int stringlen)
 	char buf[128];
 	int fd, match = 0, pos = 0, n = 0, hit = 0;
 
-	fd = open(filename, O_RDONLY);
+	fd = lws_open(filename, O_RDONLY);
 	if (fd < 0) {
 		lwsl_err("can't open auth file: %s\n", filename);
 		return 0;
@@ -812,7 +823,7 @@ lws_http_get_uri_and_method(struct lws *wsi, char **puri_ptr, int *puri_len)
 {
 	int n, count = 0;
 
-	for (n = 0; n < (int)ARRAY_SIZE(methods); n++)
+	for (n = 0; n < (int)LWS_ARRAY_SIZE(methods); n++)
 		if (lws_hdr_total_length(wsi, methods[n]))
 			count++;
 	if (!count) {
@@ -827,7 +838,7 @@ lws_http_get_uri_and_method(struct lws *wsi, char **puri_ptr, int *puri_len)
 		return -1;
 	}
 
-	for (n = 0; n < (int)ARRAY_SIZE(methods); n++)
+	for (n = 0; n < (int)LWS_ARRAY_SIZE(methods); n++)
 		if (lws_hdr_total_length(wsi, methods[n])) {
 			*puri_ptr = lws_hdr_simple_ptr(wsi, methods[n]);
 			*puri_len = lws_hdr_total_length(wsi, methods[n]);
@@ -857,7 +868,7 @@ lws_http_action(struct lws *wsi)
 	};
 
 	meth = lws_http_get_uri_and_method(wsi, &uri_ptr, &uri_len);
-	if (meth < 0 || meth >= (int)ARRAY_SIZE(method_names))
+	if (meth < 0 || meth >= (int)LWS_ARRAY_SIZE(method_names))
 		goto bail_nuke_ah;
 
 	/* we insist on absolute paths */
@@ -1128,7 +1139,7 @@ lws_http_action(struct lws *wsi)
 		}
 		if (pcolon > pslash)
 			pcolon = NULL;
-		
+
 		if (pcolon)
 			n = pcolon - hit->origin;
 		else
@@ -1142,13 +1153,13 @@ lws_http_action(struct lws *wsi)
 
 		i.address = ads;
 		i.port = 80;
-		if (hit->origin_protocol == LWSMPRO_HTTPS) { 
+		if (hit->origin_protocol == LWSMPRO_HTTPS) {
 			i.port = 443;
 			i.ssl_connection = 1;
 		}
 		if (pcolon)
 			i.port = atoi(pcolon + 1);
-		
+
 		lws_snprintf(rpath, sizeof(rpath) - 1, "/%s/%s", pslash + 1,
 			     uri_ptr + hit->mountpoint_len);
 		lws_clean_url(rpath);
@@ -1164,7 +1175,7 @@ lws_http_action(struct lws *wsi)
 				p++;
 			}
 		}
-				
+
 
 		i.path = rpath;
 		i.host = i.address;
@@ -1178,7 +1189,7 @@ lws_http_action(struct lws *wsi)
 			    "from %s, to %s\n",
 			    i.address, i.port, i.path, i.ssl_connection,
 			    i.uri_replace_from, i.uri_replace_to);
-	
+
 		if (!lws_client_connect_via_info(&i)) {
 			lwsl_err("proxy connect fail\n");
 			return 1;
@@ -1714,12 +1725,31 @@ lws_http_transaction_completed(struct lws *wsi)
 {
 	int n = NO_PENDING_TIMEOUT;
 
+	if (wsi->trunc_len) {
+		/*
+		 * ...so he tried to send something large as the http reply,
+		 * it went as a partial, but he immediately said the
+		 * transaction was completed.
+		 *
+		 * Defer the transaction completed until the last part of the
+		 * partial is sent.
+		 */
+		lwsl_notice("%s: deferring due to partial\n", __func__);
+		wsi->http.deferred_transaction_completed = 1;
+
+		return 0;
+	}
+
 	lwsl_info("%s: wsi %p\n", __func__, wsi);
 
 	lws_access_log(wsi);
 
 	if (!wsi->hdr_parsing_completed) {
-		lwsl_notice("%s: ignoring, ah parsing incomplete\n", __func__);
+		char peer[64];
+		lws_get_peer_simple(wsi, peer, sizeof(peer) - 1);
+		peer[sizeof(peer) - 1] = '\0';
+		lwsl_notice("%s: (from %s) ignoring, ah parsing incomplete\n",
+				__func__, peer);
 		return 0;
 	}
 

+ 3 - 8
thirdparty/libwebsockets/roles/ws/client-parser-ws.c

@@ -450,7 +450,7 @@ ping_drop:
 			break;
 
 		case LWSWSOPC_PONG:
-			lwsl_info("client receied pong\n");
+			lwsl_info("client received pong\n");
 			lwsl_hexdump(&wsi->ws->rx_ubuf[LWS_PRE],
 				     wsi->ws->rx_ubuf_head);
 
@@ -488,9 +488,6 @@ ping_drop:
 		ebuf.token = &wsi->ws->rx_ubuf[LWS_PRE];
 		ebuf.len = wsi->ws->rx_ubuf_head;
 
-		if (wsi->ws->opcode == LWSWSOPC_PONG && !ebuf.len)
-			goto already_done;
-
 #if !defined(LWS_WITHOUT_EXTENSIONS)
 drain_extension:
 		lwsl_ext("%s: passing %d to ext\n", __func__, ebuf.len);
@@ -504,14 +501,12 @@ drain_extension:
 #endif
 		lwsl_debug("post inflate ebuf len %d\n", ebuf.len);
 
-		if (
 #if !defined(LWS_WITHOUT_EXTENSIONS)
-		    rx_draining_ext &&
-#endif
-		    !ebuf.len) {
+		if (rx_draining_ext && !ebuf.len) {
 			lwsl_debug("   --- ending drain on 0 read result\n");
 			goto already_done;
 		}
+#endif
 
 		if (wsi->ws->check_utf8 && !wsi->ws->defeat_check_utf8) {
 			if (lws_check_utf8(&wsi->ws->utf8,

+ 14 - 12
thirdparty/libwebsockets/roles/ws/ops-ws.c

@@ -1246,8 +1246,7 @@ int rops_handle_POLLOUT_ws(struct lws *wsi)
 		return LWS_HP_RET_BAIL_OK;
 	}
 
-	if (lwsi_role_client(wsi) && !wsi->socket_is_permanently_unusable &&
-	    wsi->ws->send_check_ping) {
+	if (!wsi->socket_is_permanently_unusable && wsi->ws->send_check_ping) {
 
 		lwsl_info("issuing ping on wsi %p\n", wsi);
 		wsi->ws->send_check_ping = 0;
@@ -1282,7 +1281,7 @@ int rops_handle_POLLOUT_ws(struct lws *wsi)
 	 *	       payload ordering, but since they are always complete
 	 *	       fragments control packets can interleave OK.
 	 */
-	if (lwsi_role_client(wsi) && wsi->ws->tx_draining_ext) {
+	if (wsi->ws->tx_draining_ext) {
 		lwsl_ext("SERVICING TX EXT DRAINING\n");
 		if (lws_write(wsi, NULL, 0, LWS_WRITE_CONTINUATION) < 0)
 			return LWS_HP_RET_BAIL_DIE;
@@ -1292,8 +1291,10 @@ int rops_handle_POLLOUT_ws(struct lws *wsi)
 
 	/* Priority 6: extensions
 	 */
-	if (!wsi->ws->extension_data_pending)
+	if (!wsi->ws->extension_data_pending && !wsi->ws->tx_draining_ext) {
+		lwsl_ext("%s: !wsi->ws->extension_data_pending\n", __func__);
 		return LWS_HP_RET_USER_SERVICE;
+	}
 
 	/*
 	 * check in on the active extensions, see if they
@@ -1412,15 +1413,13 @@ rops_periodic_checks_ws(struct lws_context *context, int tsi, time_t now)
 					wsi->ws->time_next_ping_check) >
 				       context->ws_ping_pong_interval) {
 
-					lwsl_info("req pp on wsi %p\n",
-						  wsi);
+					lwsl_info("req pp on wsi %p\n", wsi);
 					wsi->ws->send_check_ping = 1;
 					lws_set_timeout(wsi,
 					PENDING_TIMEOUT_WS_PONG_CHECK_SEND_PING,
 						context->timeout_secs);
 					lws_callback_on_writable(wsi);
-					wsi->ws->time_next_ping_check =
-						now;
+					wsi->ws->time_next_ping_check = now;
 				}
 				wsi = wsi->same_vh_protocol_next;
 			}
@@ -1466,6 +1465,9 @@ rops_service_flag_pending_ws(struct lws_context *context, int tsi)
 static int
 rops_close_via_role_protocol_ws(struct lws *wsi, enum lws_close_status reason)
 {
+	if (!wsi->ws)
+		return 0;
+
 	if (!wsi->ws->close_in_ping_buffer_len && /* already a reason */
 	     (reason == LWS_CLOSE_STATUS_NOSTATUS ||
 	      reason == LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY))
@@ -1512,7 +1514,7 @@ rops_close_role_ws(struct lws_context_per_thread *pt, struct lws *wsi)
 
 	if (wsi->ws->tx_draining_ext) {
 		struct lws **w = &pt->ws.tx_draining_ext_list;
-		lwsl_notice("%s: CLEARING tx_draining_ext\n", __func__);
+		lwsl_ext("%s: CLEARING tx_draining_ext\n", __func__);
 		wsi->ws->tx_draining_ext = 0;
 		/* remove us from context draining ext list */
 		while (*w) {
@@ -1563,7 +1565,7 @@ rops_write_role_protocol_ws(struct lws *wsi, unsigned char *buf, size_t len,
 		/* remove us from the list */
 		struct lws **w = &pt->ws.tx_draining_ext_list;
 
-		lwsl_notice("%s: CLEARING tx_draining_ext\n", __func__);
+		lwsl_ext("%s: CLEARING tx_draining_ext\n", __func__);
 		wsi->ws->tx_draining_ext = 0;
 		/* remove us from context draining ext list */
 		while (*w) {
@@ -1588,7 +1590,7 @@ rops_write_role_protocol_ws(struct lws *wsi, unsigned char *buf, size_t len,
 		if (!(wpt & LWS_WRITE_NO_FIN) && len)
 			*wp &= ~LWS_WRITE_NO_FIN;
 
-		lwsl_notice("FORCED draining wp to 0x%02X (stashed 0x%02X, incoming 0x%02X)\n", *wp,
+		lwsl_ext("FORCED draining wp to 0x%02X (stashed 0x%02X, incoming 0x%02X)\n", *wp,
 				wsi->ws->tx_draining_stashed_wp, wpt);
 		// assert(0);
 	}
@@ -1644,7 +1646,7 @@ rops_write_role_protocol_ws(struct lws *wsi, unsigned char *buf, size_t len,
 		// lwsl_notice("ext processed %d plaintext into %d compressed (wp 0x%x)\n", m, (int)ebuf.len, *wp);
 
 		if (n && ebuf.len) {
-			lwsl_notice("write drain len %d (wp 0x%x) SETTING tx_draining_ext\n", (int)ebuf.len, *wp);
+			lwsl_ext("write drain len %d (wp 0x%x) SETTING tx_draining_ext\n", (int)ebuf.len, *wp);
 			/* extension requires further draining */
 			wsi->ws->tx_draining_ext = 1;
 			wsi->ws->tx_draining_ext_list = pt->ws.tx_draining_ext_list;

+ 1 - 1
thirdparty/libwebsockets/tls/mbedtls/mbedtls-server.c

@@ -631,7 +631,7 @@ lws_tls_acme_sni_csr_create(struct lws_context *context, const char *elements[],
 
 	/* subject must be formatted like "C=TW,O=warmcat,CN=myserver" */
 
-	for (n = 0; n < (int)ARRAY_SIZE(x5); n++) {
+	for (n = 0; n < (int)LWS_ARRAY_SIZE(x5); n++) {
 		if (p != subject)
 			*p++ = ',';
 		if (elements[n])

+ 0 - 2
thirdparty/libwebsockets/tls/mbedtls/ssl.c

@@ -121,8 +121,6 @@ lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len)
 	if (wsi->vhost)
 		wsi->vhost->conn_stats.rx += n;
 
-	lws_restart_ws_ping_pong_timer(wsi);
-
 	/*
 	 * if it was our buffer that limited what we read,
 	 * check if SSL has additional data pending inside SSL buffers.

+ 4 - 0
thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_types.h

@@ -37,7 +37,11 @@ typedef void RSA;
 typedef void STACK;
 typedef void BIO;
 
+#if defined(WIN32) || defined(_WIN32)
+#define ossl_inline __inline
+#else
 #define ossl_inline inline
+#endif
 
 #define SSL_METHOD_CALL(f, s, ...)        s->method->func->ssl_##f(s, ##__VA_ARGS__)
 #define X509_METHOD_CALL(f, x, ...)       x->method->x509_##f(x, ##__VA_ARGS__)

+ 5 - 5
thirdparty/libwebsockets/uwp_fixes.diff

@@ -1,15 +1,15 @@
 diff --git a/thirdparty/libwebsockets/plat/lws-plat-win.c b/thirdparty/libwebsockets/plat/lws-plat-win.c
-index 948db6289..511e29739 100644
+index bd513b494..1850b6425 100644
 --- a/thirdparty/libwebsockets/plat/lws-plat-win.c
 +++ b/thirdparty/libwebsockets/plat/lws-plat-win.c
-@@ -635,9 +635,20 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
+@@ -641,9 +641,20 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
  	HANDLE ret;
  	WCHAR buf[MAX_PATH];
  	lws_fop_fd_t fop_fd;
 -	LARGE_INTEGER llFileSize = {0};
 +	FILE_STANDARD_INFO fInfo = {0};
  
- 	MultiByteToWideChar(CP_UTF8, 0, filename, -1, buf, ARRAY_SIZE(buf));
+ 	MultiByteToWideChar(CP_UTF8, 0, filename, -1, buf, LWS_ARRAY_SIZE(buf));
 +
 +#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0602 // Windows 8 (minimum when UWP_ENABLED, but can be used in Windows builds)
 +	CREATEFILE2_EXTENDED_PARAMETERS extParams = {0};
@@ -24,7 +24,7 @@ index 948db6289..511e29739 100644
  	if (((*flags) & 7) == _O_RDONLY) {
  		ret = CreateFileW(buf, GENERIC_READ, FILE_SHARE_READ,
  			  NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-@@ -645,6 +656,7 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
+@@ -651,6 +662,7 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
  		ret = CreateFileW(buf, GENERIC_WRITE, 0, NULL,
  			  CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  	}
@@ -32,7 +32,7 @@ index 948db6289..511e29739 100644
  
  	if (ret == LWS_INVALID_FILE)
  		goto bail;
-@@ -657,9 +669,9 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
+@@ -663,9 +675,9 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
  	fop_fd->fd = ret;
  	fop_fd->filesystem_priv = NULL; /* we don't use it */
  	fop_fd->flags = *flags;

+ 153 - 153
thirdparty/libwebsockets/win32helpers/getopt.c

@@ -1,153 +1,153 @@
-/*	$NetBSD: getopt.c,v 1.16 1999/12/02 13:15:56 kleink Exp $	*/
-
-/*
- * Copyright (c) 1987, 1993, 1994
- *	The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if 0
-static char sccsid[] = "@(#)getopt.c	8.3 (Berkeley) 4/27/95";
-#endif
-
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-
-#define __P(x) x
-#define _DIAGASSERT(x) assert(x)
-
-#ifdef __weak_alias
-__weak_alias(getopt,_getopt);
-#endif
-
-
-int	opterr = 1,		/* if error message should be printed */
-	optind = 1,		/* index into parent argv vector */
-	optopt,			/* character checked for validity */
-	optreset;		/* reset getopt */
-char	*optarg;		/* argument associated with option */
-
-static char * _progname __P((char *));
-int getopt_internal __P((int, char * const *, const char *));
-
-static char *
-_progname(nargv0)
-	char * nargv0;
-{
-	char * tmp;
-
-	_DIAGASSERT(nargv0 != NULL);
-
-	tmp = strrchr(nargv0, '/');
-	if (tmp)
-		tmp++;
-	else
-		tmp = nargv0;
-	return(tmp);
-}
-
-#define	BADCH	(int)'?'
-#define	BADARG	(int)':'
-#define	EMSG	""
-
-/*
- * getopt --
- *	Parse argc/argv argument vector.
- */
-int
-getopt(nargc, nargv, ostr)
-	int nargc;
-	char * const nargv[];
-	const char *ostr;
-{
-	static char *__progname = 0;
-	static char *place = EMSG;		/* option letter processing */
-	char *oli;				/* option letter list index */
-        __progname = __progname?__progname:_progname(*nargv);
-
-	_DIAGASSERT(nargv != NULL);
-	_DIAGASSERT(ostr != NULL);
-
-	if (optreset || !*place) {		/* update scanning pointer */
-		optreset = 0;
-		if (optind >= nargc || *(place = nargv[optind]) != '-') {
-			place = EMSG;
-			return (-1);
-		}
-		if (place[1] && *++place == '-'	/* found "--" */
-		    && place[1] == '\0') {
-			++optind;
-			place = EMSG;
-			return (-1);
-		}
-	}					/* option letter okay? */
-	if ((optopt = (int)*place++) == (int)':' ||
-	    !(oli = strchr(ostr, optopt))) {
-		/*
-		 * if the user didn't specify '-' as an option,
-		 * assume it means -1.
-		 */
-		if (optopt == (int)'-')
-			return (-1);
-		if (!*place)
-			++optind;
-		if (opterr && *ostr != ':')
-			(void)fprintf(stderr,
-			    "%s: illegal option -- %c\n", __progname, optopt);
-		return (BADCH);
-	}
-	if (*++oli != ':') {			/* don't need argument */
-		optarg = NULL;
-		if (!*place)
-			++optind;
-	}
-	else {					/* need an argument */
-		if (*place)			/* no white space */
-			optarg = place;
-		else if (nargc <= ++optind) {	/* no arg */
-			place = EMSG;
-			if (*ostr == ':')
-				return (BADARG);
-			if (opterr)
-				(void)fprintf(stderr,
-				    "%s: option requires an argument -- %c\n",
-				    __progname, optopt);
-			return (BADCH);
-		}
-	 	else				/* white space */
-			optarg = nargv[optind];
-		place = EMSG;
-		++optind;
-	}
-	return (optopt);			/* dump back option letter */
-}
-
+/*	$NetBSD: getopt.c,v 1.16 1999/12/02 13:15:56 kleink Exp $	*/
+
+/*
+ * Copyright (c) 1987, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+static char sccsid[] = "@(#)getopt.c	8.3 (Berkeley) 4/27/95";
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#define __P(x) x
+#define _DIAGASSERT(x) assert(x)
+
+#ifdef __weak_alias
+__weak_alias(getopt,_getopt);
+#endif
+
+
+int	opterr = 1,		/* if error message should be printed */
+	optind = 1,		/* index into parent argv vector */
+	optopt,			/* character checked for validity */
+	optreset;		/* reset getopt */
+char	*optarg;		/* argument associated with option */
+
+static char * _progname __P((char *));
+int getopt_internal __P((int, char * const *, const char *));
+
+static char *
+_progname(nargv0)
+	char * nargv0;
+{
+	char * tmp;
+
+	_DIAGASSERT(nargv0 != NULL);
+
+	tmp = strrchr(nargv0, '/');
+	if (tmp)
+		tmp++;
+	else
+		tmp = nargv0;
+	return(tmp);
+}
+
+#define	BADCH	(int)'?'
+#define	BADARG	(int)':'
+#define	EMSG	""
+
+/*
+ * getopt --
+ *	Parse argc/argv argument vector.
+ */
+int
+getopt(nargc, nargv, ostr)
+	int nargc;
+	char * const nargv[];
+	const char *ostr;
+{
+	static char *__progname = 0;
+	static char *place = EMSG;		/* option letter processing */
+	char *oli;				/* option letter list index */
+        __progname = __progname?__progname:_progname(*nargv);
+
+	_DIAGASSERT(nargv != NULL);
+	_DIAGASSERT(ostr != NULL);
+
+	if (optreset || !*place) {		/* update scanning pointer */
+		optreset = 0;
+		if (optind >= nargc || *(place = nargv[optind]) != '-') {
+			place = EMSG;
+			return (-1);
+		}
+		if (place[1] && *++place == '-'	/* found "--" */
+		    && place[1] == '\0') {
+			++optind;
+			place = EMSG;
+			return (-1);
+		}
+	}					/* option letter okay? */
+	if ((optopt = (int)*place++) == (int)':' ||
+	    !(oli = strchr(ostr, optopt))) {
+		/*
+		 * if the user didn't specify '-' as an option,
+		 * assume it means -1.
+		 */
+		if (optopt == (int)'-')
+			return (-1);
+		if (!*place)
+			++optind;
+		if (opterr && *ostr != ':')
+			(void)fprintf(stderr,
+			    "%s: illegal option -- %c\n", __progname, optopt);
+		return (BADCH);
+	}
+	if (*++oli != ':') {			/* don't need argument */
+		optarg = NULL;
+		if (!*place)
+			++optind;
+	}
+	else {					/* need an argument */
+		if (*place)			/* no white space */
+			optarg = place;
+		else if (nargc <= ++optind) {	/* no arg */
+			place = EMSG;
+			if (*ostr == ':')
+				return (BADARG);
+			if (opterr)
+				(void)fprintf(stderr,
+				    "%s: option requires an argument -- %c\n",
+				    __progname, optopt);
+			return (BADCH);
+		}
+	 	else				/* white space */
+			optarg = nargv[optind];
+		place = EMSG;
+		++optind;
+	}
+	return (optopt);			/* dump back option letter */
+}
+

+ 240 - 240
thirdparty/libwebsockets/win32helpers/getopt_long.c

@@ -1,240 +1,240 @@
-
-/*
- * Copyright (c) 1987, 1993, 1994, 1996
- *	The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "getopt.h"
-
-#define lws_ptr_diff(head, tail) \
-			((int)((char *)(head) - (char *)(tail)))
-
-extern int	  opterr;	/* if error message should be printed */
-extern int	  optind;	/* index into parent argv vector */
-extern int	  optopt;	/* character checked for validity */
-extern int	  optreset;	/* reset getopt */
-extern char *optarg;	/* argument associated with option */
-
-#define __P(x) x
-#define _DIAGASSERT(x) assert(x)
-
-static char * __progname __P((char *));
-int getopt_internal __P((int, char * const *, const char *));
-
-static char *
-__progname(nargv0)
-	char * nargv0;
-{
-	char * tmp;
-
-	_DIAGASSERT(nargv0 != NULL);
-
-	tmp = strrchr(nargv0, '/');
-	if (tmp)
-		tmp++;
-	else
-		tmp = nargv0;
-	return(tmp);
-}
-
-#define	BADCH	(int)'?'
-#define	BADARG	(int)':'
-#define	EMSG	""
-
-/*
- * getopt --
- *	Parse argc/argv argument vector.
- */
-int
-getopt_internal(nargc, nargv, ostr)
-	int nargc;
-	char * const *nargv;
-	const char *ostr;
-{
-	static char *place = EMSG;		/* option letter processing */
-	char *oli;				/* option letter list index */
-
-	_DIAGASSERT(nargv != NULL);
-	_DIAGASSERT(ostr != NULL);
-
-	if (optreset || !*place) {		/* update scanning pointer */
-		optreset = 0;
-		if (optind >= nargc || *(place = nargv[optind]) != '-') {
-			place = EMSG;
-			return (-1);
-		}
-		if (place[1] && *++place == '-') {	/* found "--" */
-			/* ++optind; */
-			place = EMSG;
-			return (-2);
-		}
-	}					/* option letter okay? */
-	if ((optopt = (int)*place++) == (int)':' ||
-	    !(oli = strchr(ostr, optopt))) {
-		/*
-		 * if the user didn't specify '-' as an option,
-		 * assume it means -1.
-		 */
-		if (optopt == (int)'-')
-			return (-1);
-		if (!*place)
-			++optind;
-		if (opterr && *ostr != ':')
-			(void)fprintf(stderr,
-			    "%s: illegal option -- %c\n", __progname(nargv[0]), optopt);
-		return (BADCH);
-	}
-	if (*++oli != ':') {			/* don't need argument */
-		optarg = NULL;
-		if (!*place)
-			++optind;
-	} else {				/* need an argument */
-		if (*place)			/* no white space */
-			optarg = place;
-		else if (nargc <= ++optind) {	/* no arg */
-			place = EMSG;
-			if ((opterr) && (*ostr != ':'))
-				(void)fprintf(stderr,
-				    "%s: option requires an argument -- %c\n",
-				    __progname(nargv[0]), optopt);
-			return (BADARG);
-		} else				/* white space */
-			optarg = nargv[optind];
-		place = EMSG;
-		++optind;
-	}
-	return (optopt);			/* dump back option letter */
-}
-
-#if 0
-/*
- * getopt --
- *	Parse argc/argv argument vector.
- */
-int
-getopt2(nargc, nargv, ostr)
-	int nargc;
-	char * const *nargv;
-	const char *ostr;
-{
-	int retval;
-
-	if ((retval = getopt_internal(nargc, nargv, ostr)) == -2) {
-		retval = -1;
-		++optind; 
-	}
-	return(retval);
-}
-#endif
-
-/*
- * getopt_long --
- *	Parse argc/argv argument vector.
- */
-int
-getopt_long(nargc, nargv, options, long_options, index)
-	int nargc;
-	char ** nargv;
-	char * options;
-	struct option * long_options;
-	int * index;
-{
-	int retval;
-
-	_DIAGASSERT(nargv != NULL);
-	_DIAGASSERT(options != NULL);
-	_DIAGASSERT(long_options != NULL);
-	/* index may be NULL */
-
-	if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
-		char *current_argv = nargv[optind++] + 2, *has_equal;
-		int i, current_argv_len, match = -1;
-
-		if (*current_argv == '\0') {
-			return(-1);
-		}
-		if ((has_equal = strchr(current_argv, '=')) != NULL) {
-			current_argv_len = lws_ptr_diff(has_equal, current_argv);
-			has_equal++;
-		} else
-			current_argv_len = (int)strlen(current_argv);
-
-		for (i = 0; long_options[i].name; i++) { 
-			if (strncmp(current_argv, long_options[i].name, current_argv_len))
-				continue;
-
-			if (strlen(long_options[i].name) == (unsigned)current_argv_len) { 
-				match = i;
-				break;
-			}
-			if (match == -1)
-				match = i;
-		}
-		if (match != -1) {
-			if (long_options[match].has_arg == required_argument ||
-			    long_options[match].has_arg == optional_argument) {
-				if (has_equal)
-					optarg = has_equal;
-				else
-					optarg = nargv[optind++];
-			}
-			if ((long_options[match].has_arg == required_argument)
-			    && (optarg == NULL)) {
-				/*
-				 * Missing argument, leading :
-				 * indicates no error should be generated
-				 */
-				if ((opterr) && (*options != ':'))
-					(void)fprintf(stderr,
-				      "%s: option requires an argument -- %s\n",
-				      __progname(nargv[0]), current_argv);
-				return (BADARG);
-			}
-		} else { /* No matching argument */
-			if ((opterr) && (*options != ':'))
-				(void)fprintf(stderr,
-				    "%s: illegal option -- %s\n", __progname(nargv[0]), current_argv);
-			return (BADCH);
-		}
-		if (long_options[match].flag) {
-			*long_options[match].flag = long_options[match].val;
-			retval = 0;
-		} else 
-			retval = long_options[match].val;
-		if (index)
-			*index = match;
-	}
-	return(retval);
-}
+
+/*
+ * Copyright (c) 1987, 1993, 1994, 1996
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "getopt.h"
+
+#define lws_ptr_diff(head, tail) \
+			((int)((char *)(head) - (char *)(tail)))
+
+extern int	  opterr;	/* if error message should be printed */
+extern int	  optind;	/* index into parent argv vector */
+extern int	  optopt;	/* character checked for validity */
+extern int	  optreset;	/* reset getopt */
+extern char *optarg;	/* argument associated with option */
+
+#define __P(x) x
+#define _DIAGASSERT(x) assert(x)
+
+static char * __progname __P((char *));
+int getopt_internal __P((int, char * const *, const char *));
+
+static char *
+__progname(nargv0)
+	char * nargv0;
+{
+	char * tmp;
+
+	_DIAGASSERT(nargv0 != NULL);
+
+	tmp = strrchr(nargv0, '/');
+	if (tmp)
+		tmp++;
+	else
+		tmp = nargv0;
+	return(tmp);
+}
+
+#define	BADCH	(int)'?'
+#define	BADARG	(int)':'
+#define	EMSG	""
+
+/*
+ * getopt --
+ *	Parse argc/argv argument vector.
+ */
+int
+getopt_internal(nargc, nargv, ostr)
+	int nargc;
+	char * const *nargv;
+	const char *ostr;
+{
+	static char *place = EMSG;		/* option letter processing */
+	char *oli;				/* option letter list index */
+
+	_DIAGASSERT(nargv != NULL);
+	_DIAGASSERT(ostr != NULL);
+
+	if (optreset || !*place) {		/* update scanning pointer */
+		optreset = 0;
+		if (optind >= nargc || *(place = nargv[optind]) != '-') {
+			place = EMSG;
+			return (-1);
+		}
+		if (place[1] && *++place == '-') {	/* found "--" */
+			/* ++optind; */
+			place = EMSG;
+			return (-2);
+		}
+	}					/* option letter okay? */
+	if ((optopt = (int)*place++) == (int)':' ||
+	    !(oli = strchr(ostr, optopt))) {
+		/*
+		 * if the user didn't specify '-' as an option,
+		 * assume it means -1.
+		 */
+		if (optopt == (int)'-')
+			return (-1);
+		if (!*place)
+			++optind;
+		if (opterr && *ostr != ':')
+			(void)fprintf(stderr,
+			    "%s: illegal option -- %c\n", __progname(nargv[0]), optopt);
+		return (BADCH);
+	}
+	if (*++oli != ':') {			/* don't need argument */
+		optarg = NULL;
+		if (!*place)
+			++optind;
+	} else {				/* need an argument */
+		if (*place)			/* no white space */
+			optarg = place;
+		else if (nargc <= ++optind) {	/* no arg */
+			place = EMSG;
+			if ((opterr) && (*ostr != ':'))
+				(void)fprintf(stderr,
+				    "%s: option requires an argument -- %c\n",
+				    __progname(nargv[0]), optopt);
+			return (BADARG);
+		} else				/* white space */
+			optarg = nargv[optind];
+		place = EMSG;
+		++optind;
+	}
+	return (optopt);			/* dump back option letter */
+}
+
+#if 0
+/*
+ * getopt --
+ *	Parse argc/argv argument vector.
+ */
+int
+getopt2(nargc, nargv, ostr)
+	int nargc;
+	char * const *nargv;
+	const char *ostr;
+{
+	int retval;
+
+	if ((retval = getopt_internal(nargc, nargv, ostr)) == -2) {
+		retval = -1;
+		++optind; 
+	}
+	return(retval);
+}
+#endif
+
+/*
+ * getopt_long --
+ *	Parse argc/argv argument vector.
+ */
+int
+getopt_long(nargc, nargv, options, long_options, index)
+	int nargc;
+	char ** nargv;
+	char * options;
+	struct option * long_options;
+	int * index;
+{
+	int retval;
+
+	_DIAGASSERT(nargv != NULL);
+	_DIAGASSERT(options != NULL);
+	_DIAGASSERT(long_options != NULL);
+	/* index may be NULL */
+
+	if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
+		char *current_argv = nargv[optind++] + 2, *has_equal;
+		int i, current_argv_len, match = -1;
+
+		if (*current_argv == '\0') {
+			return(-1);
+		}
+		if ((has_equal = strchr(current_argv, '=')) != NULL) {
+			current_argv_len = lws_ptr_diff(has_equal, current_argv);
+			has_equal++;
+		} else
+			current_argv_len = (int)strlen(current_argv);
+
+		for (i = 0; long_options[i].name; i++) { 
+			if (strncmp(current_argv, long_options[i].name, current_argv_len))
+				continue;
+
+			if (strlen(long_options[i].name) == (unsigned)current_argv_len) { 
+				match = i;
+				break;
+			}
+			if (match == -1)
+				match = i;
+		}
+		if (match != -1) {
+			if (long_options[match].has_arg == required_argument ||
+			    long_options[match].has_arg == optional_argument) {
+				if (has_equal)
+					optarg = has_equal;
+				else
+					optarg = nargv[optind++];
+			}
+			if ((long_options[match].has_arg == required_argument)
+			    && (optarg == NULL)) {
+				/*
+				 * Missing argument, leading :
+				 * indicates no error should be generated
+				 */
+				if ((opterr) && (*options != ':'))
+					(void)fprintf(stderr,
+				      "%s: option requires an argument -- %s\n",
+				      __progname(nargv[0]), current_argv);
+				return (BADARG);
+			}
+		} else { /* No matching argument */
+			if ((opterr) && (*options != ':'))
+				(void)fprintf(stderr,
+				    "%s: illegal option -- %s\n", __progname(nargv[0]), current_argv);
+			return (BADCH);
+		}
+		if (long_options[match].flag) {
+			*long_options[match].flag = long_options[match].val;
+			retval = 0;
+		} else 
+			retval = long_options[match].val;
+		if (index)
+			*index = match;
+	}
+	return(retval);
+}

+ 35 - 35
thirdparty/libwebsockets/win32helpers/gettimeofday.c

@@ -1,36 +1,36 @@
-#include <time.h>
-#include <windows.h> //I've omitted context line
-
-#include "gettimeofday.h"
-
-int gettimeofday(struct timeval *tv, struct timezone *tz)
-{
-	FILETIME ft;
-	unsigned __int64 tmpres = 0;
-	static int tzflag;
-
-	if (NULL != tv) {
-		GetSystemTimeAsFileTime(&ft);
-
-		tmpres |= ft.dwHighDateTime;
-		tmpres <<= 32;
-		tmpres |= ft.dwLowDateTime;
-
-		/*converting file time to unix epoch*/
-		tmpres /= 10;  /*convert into microseconds*/
+#include <time.h>
+#include <windows.h> //I've omitted context line
+
+#include "gettimeofday.h"
+
+int gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+	FILETIME ft;
+	unsigned __int64 tmpres = 0;
+	static int tzflag;
+
+	if (NULL != tv) {
+		GetSystemTimeAsFileTime(&ft);
+
+		tmpres |= ft.dwHighDateTime;
+		tmpres <<= 32;
+		tmpres |= ft.dwLowDateTime;
+
+		/*converting file time to unix epoch*/
+		tmpres /= 10;  /*convert into microseconds*/
 		tmpres -= DELTA_EPOCH_IN_MICROSECS;
-		tv->tv_sec = (long)(tmpres / 1000000UL);
-		tv->tv_usec = (long)(tmpres % 1000000UL);
-	}
- 
-	if (NULL != tz) {
-		if (!tzflag) {
-			_tzset();
-			tzflag++;
-		}
-		tz->tz_minuteswest = _timezone / 60;
-		tz->tz_dsttime = _daylight;
-	}
-
-	return 0;
-}
+		tv->tv_sec = (long)(tmpres / 1000000UL);
+		tv->tv_usec = (long)(tmpres % 1000000UL);
+	}
+ 
+	if (NULL != tz) {
+		if (!tzflag) {
+			_tzset();
+			tzflag++;
+		}
+		tz->tz_minuteswest = _timezone / 60;
+		tz->tz_dsttime = _daylight;
+	}
+
+	return 0;
+}