{"schema":"libjg2-1",
"vpath":"/git/",
"avatar":"/git/avatar/",
"alang":"",
"gen_ut":1746503768,
"reponame":"libwebsockets",
"desc":"libwebsockets lightweight C networking library",
"owner": { "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" },"url":"https://libwebsockets.org/repo/libwebsockets",
"f":3,
"items": [
{"schema":"libjg2-1",
"cid":"e15e894304ec8b9d3788e0bfb5c461c5",
"commit": {"type":"commit",
"time": 1396058080,
"time_ofs": 480,
"oid_tree": { "oid": "410db8b6dd29027204e4e060e1cfccd5c37be88a", "alias": []},
"oid":{ "oid": "0fc37b64f6553a7433218d09a96de0ed5138f873", "alias": []},
"msg": "windows Use WSAWaitForMultipleEvents() instead of poll() on Windows",
"sig_commit": { "git_time": { "time": 1396058080, "offset": 480 }, "name": "Andy Green", "email": "andy.green@linaro.org", "md5": "4863edaebb4491aa6049a4d2d9c98c2c" },
"sig_author": { "git_time": { "time": 1396017896, "offset": 60 }, "name": "Patrick Gansterer", "email": "paroga@paroga.com", "md5": "dada87ff8dd864ae5cc285e90ef853e2" }},
"body": "windows Use WSAWaitForMultipleEvents() instead of poll() on Windows"
,
"diff": "diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c\nindex b7d84b8..54c0c5f 100644\n--- a/lib/libwebsockets.c\n+++ b/lib/libwebsockets.c\n@@ -185,6 +185,10 @@ insert_wsi_socket_into_fds(struct libwebsocket_context *context,\n \n #endif /* LWS_USE_LIBEV */\n \tcontext-\u003efds[context-\u003efds_count++].revents \u003d 0;\n+#ifdef _WIN32\n+\tcontext-\u003eevents[context-\u003efds_count] \u003d WSACreateEvent();\n+\tWSAEventSelect(wsi-\u003esock, context-\u003eevents[context-\u003efds_count], LWS_POLLIN);\n+#endif\n \n \t/* external POLL support via protocol 0 */\n \tcontext-\u003eprotocols[0].callback(context, wsi,\n@@ -229,6 +233,10 @@ remove_wsi_socket_from_fds(struct libwebsocket_context *context,\n \n \t/* have the last guy take up the vacant slot */\n \tcontext-\u003efds[m] \u003d context-\u003efds[context-\u003efds_count];\n+#ifdef _WIN32\n+\tWSACloseEvent(context-\u003eevents[m + 1]);\n+\tcontext-\u003eevents[m + 1] \u003d context-\u003eevents[context-\u003efds_count + 1];\n+#endif\n \t/*\n \t * end guy's fds_lookup entry remains unchanged\n \t * (still same fd pointing to same wsi)\n@@ -765,6 +773,9 @@ int lws_set_socket_options(struct libwebsocket_context *context, int fd)\n \n LWS_VISIBLE int lws_send_pipe_choked(struct libwebsocket *wsi)\n {\n+#ifdef _WIN32\n+\treturn wsi-\u003esock_send_blocking;\n+#else\n \tstruct pollfd fds;\n \n \t/* treat the fact we got a truncated send pending as if we're choked */\n@@ -784,6 +795,7 @@ LWS_VISIBLE int lws_send_pipe_choked(struct libwebsocket *wsi)\n \t/* okay to send another packet without blocking */\n \n \treturn 0;\n+#endif\n }\n \n int\n@@ -974,6 +986,23 @@ libwebsocket_service_timeout_check(struct libwebsocket_context *context,\n \treturn 0;\n }\n \n+static int lws_poll_listen_fd(struct pollfd* fd)\n+{\n+#ifdef _WIN32\n+\tfd_set readfds;\n+\tstruct timeval tv \u003d { 0, 0 };\n+\n+\tassert(fd-\u003eevents \u003d\u003d POLLIN);\n+\n+\tFD_ZERO(\u0026readfds);\n+\tFD_SET(fd-\u003efd, \u0026readfds);\n+\n+\treturn select(fd-\u003efd + 1, \u0026readfds, NULL, NULL, \u0026tv);\n+#else\n+\treturn poll(fd, 1, 0);\n+#endif\n+}\n+\n /**\n * libwebsocket_service_fd() - Service polled socket with something waiting\n * @context:\tWebsocket context\n@@ -1103,8 +1132,7 @@ libwebsocket_service_fd(struct libwebsocket_context *context,\n \t\t\t\t * even with extpoll, we prepared this\n \t\t\t\t * internal fds for listen\n \t\t\t\t */\n-\t\t\t\tn \u003d poll(\u0026context-\u003efds[listen_socket_fds_index],\n-\t\t\t\t\t\t\t\t\t 1, 0);\n+\t\t\t\tn \u003d lws_poll_listen_fd(\u0026context-\u003efds[listen_socket_fds_index]);\n \t\t\t\tif (n \u003e 0) { /* there's a conn waiting for us */\n \t\t\t\t\tlibwebsocket_service_fd(context,\n \t\t\t\t\t\t\u0026context-\u003e\n@@ -1389,6 +1417,10 @@ libwebsocket_context_destroy(struct libwebsocket_context *context)\n \n \n #if defined(WIN32) || defined(_WIN32)\n+\tif (context-\u003eevents) {\n+\t\tWSACloseEvent(context-\u003eevents[0]);\n+\t\tfree(context-\u003eevents);\n+\t}\n #else\n \tclose(context-\u003edummy_pipe_fds[0]);\n \tclose(context-\u003edummy_pipe_fds[1]);\n@@ -1470,8 +1502,15 @@ LWS_VISIBLE int\n libwebsocket_service(struct libwebsocket_context *context, int timeout_ms)\n {\n \tint n;\n+#ifdef _WIN32\n+\tint i;\n+\tDWORD ev;\n+\tWSANETWORKEVENTS networkevents;\n+\tstruct pollfd *pfd;\n+#else\n \tint m;\n \tchar buf;\n+#endif\n \n \t/* stay dead once we are dead */\n \n@@ -1484,6 +1523,53 @@ libwebsocket_service(struct libwebsocket_context *context, int timeout_ms)\n #endif /* LWS_USE_LIBEV */\n \tcontext-\u003eservice_tid \u003d context-\u003eprotocols[0].callback(context, NULL,\n \t\t\t\t LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0);\n+\n+#ifdef _WIN32\n+\tfor (i \u003d 0; i \u003c context-\u003efds_count; ++i) {\n+\t\tpfd \u003d \u0026context-\u003efds[i];\n+\t\tif (pfd-\u003efd \u003d\u003d context-\u003elisten_service_fd)\n+\t\t\tcontinue;\n+\t\tif (pfd-\u003eevents \u0026 POLLOUT) {\n+\t\t\tif (context-\u003elws_lookup[pfd-\u003efd]-\u003esock_send_blocking)\n+\t\t\t\tcontinue;\n+\t\t\tpfd-\u003erevents \u003d POLLOUT;\n+\t\t\tn \u003d libwebsocket_service_fd(context, pfd);\n+\t\t\tif (n \u003c 0)\n+\t\t\t\treturn n;\n+\t\t}\n+\t}\n+\n+\tev \u003d WSAWaitForMultipleEvents(context-\u003efds_count + 1, context-\u003eevents, FALSE, timeout_ms, FALSE);\n+\tif (ev \u003d\u003d WSA_WAIT_TIMEOUT) {\n+\t\tlibwebsocket_service_fd(context, NULL);\n+\t\treturn 0;\n+\t}\n+\n+\tif (ev \u003d\u003d WSA_WAIT_EVENT_0) {\n+\t\tWSAResetEvent(context-\u003eevents[0]);\n+\t\treturn 0;\n+\t}\n+\n+\tif (ev \u003c WSA_WAIT_EVENT_0 || ev \u003e WSA_WAIT_EVENT_0 + context-\u003efds_count)\n+\t\treturn -1;\n+\n+\tpfd \u003d \u0026context-\u003efds[ev - WSA_WAIT_EVENT_0 - 1];\n+\n+\tif (WSAEnumNetworkEvents(pfd-\u003efd, context-\u003eevents[ev - WSA_WAIT_EVENT_0],\n+\t\t\t\u0026networkevents) \u003d\u003d SOCKET_ERROR) {\n+\t\tlwsl_err(\u0022WSAEnumNetworkEvents() failed with error %d\u005cn\u0022, LWS_ERRNO);\n+\t\treturn -1;\n+\t}\n+\n+\tpfd-\u003erevents \u003d (networkevents.lNetworkEvents \u0026 LWS_POLLIN) ? POLLIN : 0;\n+\n+\tif (networkevents.lNetworkEvents \u0026 LWS_POLLOUT) {\n+\t\tcontext-\u003elws_lookup[pfd-\u003efd]-\u003esock_send_blocking \u003d FALSE;\n+\t\tpfd-\u003erevents |\u003d POLLOUT;\n+\t}\n+\n+\treturn libwebsocket_service_fd(context, pfd);\n+#else\n \tn \u003d poll(context-\u003efds, context-\u003efds_count, timeout_ms);\n \tcontext-\u003eservice_tid \u003d 0;\n \n@@ -1504,13 +1590,13 @@ libwebsocket_service(struct libwebsocket_context *context, int timeout_ms)\n \tfor (n \u003d 0; n \u003c context-\u003efds_count; n++) {\n \t\tif (!context-\u003efds[n].revents)\n \t\t\tcontinue;\n-#ifndef _WIN32\n+\n \t\tif (context-\u003efds[n].fd \u003d\u003d context-\u003edummy_pipe_fds[0]) {\n \t\t\tif (read(context-\u003efds[n].fd, \u0026buf, 1) !\u003d 1)\n \t\t\t\tlwsl_err(\u0022Cannot read from dummy pipe.\u0022);\n \t\t\tcontinue;\n \t\t}\n-#endif\n+\n \t\tm \u003d libwebsocket_service_fd(context, \u0026context-\u003efds[n]);\n \t\tif (m \u003c 0)\n \t\t\treturn -1;\n@@ -1520,6 +1606,7 @@ libwebsocket_service(struct libwebsocket_context *context, int timeout_ms)\n \t}\n \n \treturn 0;\n+#endif\n }\n \n /**\n@@ -1528,13 +1615,13 @@ libwebsocket_service(struct libwebsocket_context *context, int timeout_ms)\n *\n *\tThis function let a call to libwebsocket_service() waiting for a timeout\n *\timmediately return.\n- *\n- *\tAt the moment this functionality cannot be used on Windows.\n */\n LWS_VISIBLE void\n libwebsocket_cancel_service(struct libwebsocket_context *context)\n {\n-#ifndef _WIN32\n+#ifdef _WIN32\n+\tWSASetEvent(context-\u003eevents[0]);\n+#else\n \tchar buf \u003d 0;\n \tif (write(context-\u003edummy_pipe_fds[1], \u0026buf, sizeof(buf)) !\u003d 1)\n \t\tlwsl_err(\u0022Cannot write to dummy pipe.\u0022);\n@@ -1649,20 +1736,24 @@ void\n lws_change_pollfd(struct libwebsocket *wsi, int _and, int _or)\n {\n \tstruct libwebsocket_context *context \u003d wsi-\u003eprotocol-\u003eowning_server;\n-\tint events;\n \tint tid;\n \tint sampled_tid;\n+\tstruct pollfd *pfd;\n \tstruct libwebsocket_pollargs pa;\n+#ifdef _WIN32\n+\tlong networkevents \u003d FD_WRITE;\n+#endif\n \n+\tpfd \u003d \u0026context-\u003efds[wsi-\u003eposition_in_fds_table];\n \tpa.fd \u003d wsi-\u003esock;\n \n \tcontext-\u003eprotocols[0].callback(context, wsi,\n \t\tLWS_CALLBACK_LOCK_POLL,\n \t\twsi-\u003euser_space, (void *) \u0026pa, 0);\n \n-\tpa.prev_events \u003d events \u003d context-\u003efds[wsi-\u003eposition_in_fds_table].events;\n+\tpa.prev_events \u003d pfd-\u003eevents;\n \n-\tpa.events \u003d context-\u003efds[wsi-\u003eposition_in_fds_table].events \u003d (events \u0026 ~_and) | _or;\n+\tpa.events \u003d pfd-\u003eevents \u003d (pfd-\u003eevents \u0026 ~_and) | _or;\n \n \tcontext-\u003eprotocols[0].callback(context, wsi,\n \t\t\tLWS_CALLBACK_CHANGE_MODE_POLL_FD,\n@@ -1675,7 +1766,18 @@ lws_change_pollfd(struct libwebsocket *wsi, int _and, int _or)\n \t * ... and the service thread is waiting ...\n \t * then cancel it to force a restart with our changed events\n \t */\n-\tif (events !\u003d context-\u003efds[wsi-\u003eposition_in_fds_table].events) {\n+\tif (pa.prev_events !\u003d pa.events) {\n+#ifdef _WIN32\n+\t\tif ((pfd-\u003eevents \u0026 POLLIN))\n+\t\t\tnetworkevents |\u003d LWS_POLLIN;\n+\n+\t\tif (WSAEventSelect(wsi-\u003esock,\n+\t\t\tcontext-\u003eevents[wsi-\u003eposition_in_fds_table + 1],\n+\t\t\tnetworkevents) \u003d\u003d SOCKET_ERROR) {\n+\t\t\tlwsl_err(\u0022WSAEventSelect() failed with error %d\u005cn\u0022, LWS_ERRNO);\n+\t\t}\n+#endif\n+\n \t\tsampled_tid \u003d context-\u003eservice_tid;\n \t\tif (sampled_tid) {\n \t\t\ttid \u003d context-\u003eprotocols[0].callback(context, NULL,\n@@ -2144,20 +2246,6 @@ libwebsocket_create_context(struct lws_context_creation_info *info)\n \t\t\tlwsl_err(\u0022WSAStartup failed with error: %d\u005cn\u0022, err);\n \t\t\treturn NULL;\n \t\t}\n-\n-\t\t/* default to a poll() made out of select() */\n-\t\tpoll \u003d emulated_poll;\n-\n-#ifndef _WIN32_WCE\n-\t\t/* if windows socket lib available, use his WSAPoll */\n-\t\twsdll \u003d GetModuleHandle(_T(\u0022Ws2_32.dll\u0022));\n-\t\tif (wsdll)\n-\t\t\tpoll \u003d (PFNWSAPOLL)GetProcAddress(wsdll, \u0022WSAPoll\u0022);\n-\n-\t\t/* Finally fall back to emulated poll if all else fails */\n-\t\tif (!poll)\n-\t\t\tpoll \u003d emulated_poll;\n-#endif\n \t}\n #endif\n \n@@ -2219,9 +2307,23 @@ libwebsocket_create_context(struct lws_context_creation_info *info)\n \tmemset(context-\u003elws_lookup, 0, sizeof(struct libwebsocket *) *\n \t\t\t\t\t\t\tcontext-\u003emax_fds);\n \n+#ifdef _WIN32\n+\tcontext-\u003eevents \u003d (WSAEVENT *)malloc(sizeof(WSAEVENT) *\n+\t\t(context-\u003emax_fds + 1));\n+\tif (context-\u003eevents \u003d\u003d NULL) {\n+\t\tlwsl_err(\u0022Unable to allocate events array for %d connections\u005cn\u0022,\n+\t\t\tcontext-\u003emax_fds);\n+\t\tfree(context-\u003elws_lookup);\n+\t\tfree(context-\u003efds);\n+\t\tfree(context);\n+\t\treturn NULL;\n+\t}\n+#endif\n+\n \tif (!LWS_LIBEV_ENABLED(context)) {\n \t#ifdef _WIN32\n \t\tcontext-\u003efds_count \u003d 0;\n+\t\tcontext-\u003eevents[0] \u003d WSACreateEvent();\n \t#else\n \t\tif (pipe(context-\u003edummy_pipe_fds)) {\n \t\t\tlwsl_err(\u0022Unable to create pipe\u005cn\u0022);\ndiff --git a/lib/output.c b/lib/output.c\nindex cad6897..6924566 100644\n--- a/lib/output.c\n+++ b/lib/output.c\n@@ -86,6 +86,13 @@ LWS_VISIBLE void lwsl_hexdump(void *vbuf, size_t len)\n \n #endif\n \n+static void lws_set_blocking_send(struct libwebsocket *wsi)\n+{\n+#ifdef _WIN32\n+\twsi-\u003esock_send_blocking \u003d TRUE;\n+#endif\n+}\n+\n /*\n * notice this returns number of bytes consumed, or -1\n */\n@@ -160,6 +167,8 @@ int lws_issue_raw(struct libwebsocket *wsi, unsigned char *buf, size_t len)\n \t\t\tn \u003d SSL_get_error(wsi-\u003essl, n);\n \t\t\tif (n \u003d\u003d SSL_ERROR_WANT_READ ||\n \t\t\t\t\t\tn \u003d\u003d SSL_ERROR_WANT_WRITE) {\n+\t\t\t\tif (n \u003d\u003d SSL_ERROR_WANT_WRITE)\n+\t\t\t\t\tlws_set_blocking_send(wsi);\n \t\t\t\tn \u003d 0;\n \t\t\t\tgoto handle_truncated_send;\n \n@@ -172,7 +181,10 @@ int lws_issue_raw(struct libwebsocket *wsi, unsigned char *buf, size_t len)\n \t\tn \u003d send(wsi-\u003esock, buf, len, MSG_NOSIGNAL);\n \t\tlws_latency(context, wsi, \u0022send lws_issue_raw\u0022, n, n \u003d\u003d len);\n \t\tif (n \u003c 0) {\n-\t\t\tif (LWS_ERRNO \u003d\u003d LWS_EAGAIN || LWS_ERRNO \u003d\u003d LWS_EINTR) {\n+\t\t\tif (LWS_ERRNO \u003d\u003d LWS_EAGAIN || LWS_ERRNO \u003d\u003d LWS_EWOULDBLOCK\n+\t\t\t\t || LWS_ERRNO \u003d\u003d LWS_EINTR) {\n+\t\t\t\tif (LWS_ERRNO \u003d\u003d LWS_EWOULDBLOCK)\n+\t\t\t\t\tlws_set_blocking_send(wsi);\n \t\t\t\tn \u003d 0;\n \t\t\t\tgoto handle_truncated_send;\n \t\t\t}\ndiff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h\nindex 25b45ed..e8dce85 100644\n--- a/lib/private-libwebsockets.h\n+++ b/lib/private-libwebsockets.h\n@@ -68,6 +68,8 @@\n #define LWS_EINTR WSAEINTR\n #define LWS_EISCONN WSAEISCONN\n #define LWS_EWOULDBLOCK WSAEWOULDBLOCK\n+#define LWS_POLLIN (FD_READ | FD_ACCEPT)\n+#define LWS_POLLOUT (FD_WRITE)\n \n #define compatible_close(fd) closesocket(fd);\n #ifdef __MINGW64__\n@@ -282,6 +284,9 @@ struct lws_signal_watcher {\n #endif /* LWS_USE_LIBEV */\n \n struct libwebsocket_context {\n+#ifdef _WIN32\n+\tWSAEVENT *events;\n+#endif\n \tstruct pollfd *fds;\n \tstruct libwebsocket **lws_lookup; /* fd to wsi */\n \tint fds_count;\n@@ -500,6 +505,10 @@ struct libwebsocket {\n \tBIO *client_bio;\n \tunsigned int use_ssl:2;\n #endif\n+\n+#ifdef _WIN32\n+\tBOOL sock_send_blocking;\n+#endif\n };\n \n LWS_EXTERN void\n","s":{"c":1746429956,"u": 5292}}
],"g": 2022,"chitpc": 0,"ehitpc": 0,"indexed":0
,
"ab": 0, "si": 0, "db":0, "di":0, "sat":0, "lfc": "7d0a"}