windows-service.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to
  8. * deal in the Software without restriction, including without limitation the
  9. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  10. * sell copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  22. * IN THE SOFTWARE.
  23. */
  24. #ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
  25. #define _WINSOCK_DEPRECATED_NO_WARNINGS
  26. #endif
  27. #include "private-lib-core.h"
  28. int
  29. _lws_plat_service_forced_tsi(struct lws_context *context, int tsi)
  30. {
  31. struct lws_context_per_thread *pt = &context->pt[tsi];
  32. int m, n, r;
  33. r = lws_service_flag_pending(context, tsi);
  34. /* any socket with events to service? */
  35. for (n = 0; n < (int)pt->fds_count; n++) {
  36. if (!pt->fds[n].revents)
  37. continue;
  38. m = lws_service_fd_tsi(context, &pt->fds[n], tsi);
  39. if (m < 0)
  40. return -1;
  41. /* if something closed, retry this slot */
  42. if (m)
  43. n--;
  44. }
  45. lws_service_do_ripe_rxflow(pt);
  46. return r;
  47. }
  48. extern void lws_client_conn_wait_timeout(lws_sorted_usec_list_t *sul);
  49. int
  50. _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
  51. {
  52. struct lws_context_per_thread *pt;
  53. WSANETWORKEVENTS networkevents;
  54. struct lws_pollfd *pfd;
  55. lws_usec_t timeout_us;
  56. struct lws *wsi;
  57. unsigned int i;
  58. DWORD ev;
  59. int n;
  60. /* stay dead once we are dead */
  61. if (context == NULL)
  62. return 1;
  63. pt = &context->pt[tsi];
  64. if (!pt->service_tid_detected && context->vhost_list) {
  65. lws_fakewsi_def_plwsa(pt);
  66. lws_fakewsi_prep_plwsa_ctx(context);
  67. pt->service_tid = context->vhost_list->
  68. protocols[0].callback((struct lws *)plwsa,
  69. LWS_CALLBACK_GET_THREAD_ID,
  70. NULL, NULL, 0);
  71. pt->service_tid_detected = 1;
  72. }
  73. if (timeout_ms < 0)
  74. timeout_ms = 0;
  75. else
  76. /* force a default timeout of 23 days */
  77. timeout_ms = 2000000000;
  78. timeout_us = ((lws_usec_t)timeout_ms) * LWS_US_PER_MS;
  79. if (context->event_loop_ops->run_pt)
  80. context->event_loop_ops->run_pt(context, tsi);
  81. for (i = 0; i < pt->fds_count; ++i) {
  82. pfd = &pt->fds[i];
  83. if (!(pfd->events & LWS_POLLOUT))
  84. continue;
  85. wsi = wsi_from_fd(context, pfd->fd);
  86. if (!wsi || wsi->listener)
  87. continue;
  88. if (wsi->sock_send_blocking)
  89. continue;
  90. pfd->revents = LWS_POLLOUT;
  91. n = lws_service_fd(context, pfd);
  92. if (n < 0)
  93. return -1;
  94. /*
  95. * Force WSAWaitForMultipleEvents() to check events
  96. * and then return immediately.
  97. */
  98. timeout_us = 0;
  99. /* if something closed, retry this slot */
  100. if (n)
  101. i--;
  102. }
  103. /*
  104. * service pending callbacks and get maximum wait time
  105. */
  106. {
  107. lws_usec_t us;
  108. lws_pt_lock(pt, __func__);
  109. /* don't stay in poll wait longer than next hr timeout */
  110. us = __lws_sul_service_ripe(pt->pt_sul_owner,
  111. LWS_COUNT_PT_SUL_OWNERS,
  112. lws_now_usecs());
  113. if (us && us < timeout_us)
  114. timeout_us = us;
  115. lws_pt_unlock(pt);
  116. }
  117. if (_lws_plat_service_forced_tsi(context, tsi))
  118. timeout_us = 0;
  119. /*
  120. * is there anybody with pending stuff that needs service forcing?
  121. */
  122. if (!lws_service_adjust_timeout(context, 1, tsi))
  123. timeout_us = 0;
  124. /*
  125. * WSA cannot actually tell us this from the wait... if anyone wants
  126. * POLLOUT and is not blocked for it, no need to wait since we will want
  127. * to service at least those. Still enter the wait so we can pick up
  128. * other pending things...
  129. */
  130. for (n = 0; n < (int)pt->fds_count; n++)
  131. if (pt->fds[n].fd != LWS_SOCK_INVALID &&
  132. pt->fds[n].events & LWS_POLLOUT &&
  133. !pt->fds[n].write_blocked) {
  134. timeout_us = 0;
  135. break;
  136. }
  137. // lwsl_notice("%s: to %dms\n", __func__, (int)(timeout_us / 1000));
  138. ev = WSAWaitForMultipleEvents(pt->fds_count + 1, pt->events, FALSE,
  139. (DWORD)(timeout_us / LWS_US_PER_MS),
  140. FALSE);
  141. //lwsl_notice("%s: ev 0x%x\n", __func__, ev);
  142. /*
  143. * The wait returns indicating the one event that had something, or
  144. * that we timed out, or something broken.
  145. *
  146. * Amazingly WSA can only handle 64 events, because the errors start
  147. * at ordinal 64.
  148. */
  149. if (ev >= WSA_MAXIMUM_WAIT_EVENTS &&
  150. ev != WSA_WAIT_TIMEOUT)
  151. /* some kind of error */
  152. return 0;
  153. if (!ev) {
  154. /*
  155. * The zero'th event is the cancel event specifically. Lock
  156. * the event reset so we are definitely clearing it while we
  157. * try to clear it.
  158. */
  159. EnterCriticalSection(&pt->interrupt_lock);
  160. WSAResetEvent(pt->events[0]);
  161. LeaveCriticalSection(&pt->interrupt_lock);
  162. lws_broadcast(pt, LWS_CALLBACK_EVENT_WAIT_CANCELLED, NULL, 0);
  163. return 0;
  164. }
  165. /*
  166. * Otherwise at least fds[ev - 1] has something to do...
  167. */
  168. #if defined(LWS_WITH_TLS)
  169. if (pt->context->tls_ops &&
  170. pt->context->tls_ops->fake_POLLIN_for_buffered)
  171. pt->context->tls_ops->fake_POLLIN_for_buffered(pt);
  172. #endif
  173. /*
  174. * POLLOUT for any fds that can
  175. */
  176. for (n = 0; n < (int)pt->fds_count; n++)
  177. if (pt->fds[n].fd != LWS_SOCK_INVALID &&
  178. pt->fds[n].events & LWS_POLLOUT &&
  179. !pt->fds[n].write_blocked) {
  180. struct timeval tv;
  181. fd_set se;
  182. /*
  183. * We have to check if it is blocked...
  184. * if not, do the POLLOUT handling
  185. */
  186. FD_ZERO(&se);
  187. FD_SET(pt->fds[n].fd, &se);
  188. tv.tv_sec = tv.tv_usec = 0;
  189. if (select(1, NULL, &se, NULL, &tv) != 1)
  190. pt->fds[n].write_blocked = 1;
  191. else {
  192. pt->fds[n].revents |= LWS_POLLOUT;
  193. lws_service_fd_tsi(context, &pt->fds[n], tsi);
  194. }
  195. }
  196. if (ev && ev < WSA_MAXIMUM_WAIT_EVENTS) {
  197. unsigned int err;
  198. /* handle fds[ev - 1] */
  199. if (WSAEnumNetworkEvents(pt->fds[ev - 1].fd, pt->events[ev],
  200. &networkevents) == SOCKET_ERROR) {
  201. lwsl_err("WSAEnumNetworkEvents() failed "
  202. "with error %d\n", LWS_ERRNO);
  203. return -1;
  204. }
  205. pfd = &pt->fds[ev - 1];
  206. pfd->revents = (short)networkevents.lNetworkEvents;
  207. if (!pfd->write_blocked && pfd->revents & FD_WRITE)
  208. pfd->write_blocked = 0;
  209. err = networkevents.iErrorCode[FD_CONNECT_BIT];
  210. if ((networkevents.lNetworkEvents & FD_CONNECT) &&
  211. wsi_from_fd(context, pfd->fd) &&
  212. !wsi_from_fd(context, pfd->fd)->udp) {
  213. lwsl_debug("%s: FD_CONNECT: %p\n", __func__,
  214. wsi_from_fd(context, pfd->fd));
  215. pfd->revents &= ~LWS_POLLOUT;
  216. if (err && err != LWS_EALREADY &&
  217. err != LWS_EINPROGRESS &&
  218. err != LWS_EWOULDBLOCK &&
  219. err != WSAEINVAL) {
  220. lwsl_debug("Unable to connect errno=%d\n", err);
  221. /*
  222. * the connection has definitively failed... but
  223. * do we have more DNS entries to try?
  224. */
  225. if (wsi_from_fd(context, pfd->fd)->dns_results_next) {
  226. lws_sul_schedule(context, 0,
  227. &wsi_from_fd(context, pfd->fd)->
  228. sul_connect_timeout,
  229. lws_client_conn_wait_timeout, 1);
  230. return 0;
  231. } else
  232. pfd->revents |= LWS_POLLHUP;
  233. } else
  234. if (wsi_from_fd(context, pfd->fd)) {
  235. if (wsi_from_fd(context, pfd->fd)->udp)
  236. pfd->revents |= LWS_POLLHUP;
  237. else
  238. lws_client_connect_3_connect(
  239. wsi_from_fd(context, pfd->fd),
  240. NULL, NULL,
  241. LWS_CONNECT_COMPLETION_GOOD,
  242. NULL);
  243. }
  244. }
  245. if (pfd->revents & LWS_POLLOUT) {
  246. wsi = wsi_from_fd(context, pfd->fd);
  247. if (wsi)
  248. wsi->sock_send_blocking = 0;
  249. }
  250. if (pfd->revents) {
  251. /*
  252. * On windows is somehow necessary to "acknowledge" the
  253. * POLLIN event, otherwise we never receive another one
  254. * on the TCP connection. But it breaks UDP, so only
  255. * do it on non-UDP.
  256. */
  257. wsi = wsi_from_fd(context, pfd->fd);
  258. if (wsi && !wsi->udp)
  259. recv(pfd->fd, NULL, 0, 0);
  260. lws_service_fd_tsi(context, pfd, tsi);
  261. }
  262. }
  263. return 0;
  264. }
  265. int
  266. lws_plat_service(struct lws_context *context, int timeout_ms)
  267. {
  268. return _lws_plat_service_tsi(context, timeout_ms, 0);
  269. }