blob: bf968b770708fc62f64c69d309346a16d183ed0d [file] [log] [blame]
Andy Greend4741352014-04-03 07:36:41 +08001/*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010-2014 Andy Green <andy@warmcat.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation:
9 * version 2.1 of the License.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301 USA
20 */
21
22#include "private-libwebsockets.h"
23
Andy Green7df53c52014-10-22 15:37:28 +080024static int
25lws_calllback_as_writeable(struct libwebsocket_context *context,
26 struct libwebsocket *wsi)
27{
28 int n;
29
30 switch (wsi->mode) {
31 case LWS_CONNMODE_WS_CLIENT:
32 n = LWS_CALLBACK_CLIENT_WRITEABLE;
33 break;
34 case LWS_CONNMODE_WS_SERVING:
35 n = LWS_CALLBACK_SERVER_WRITEABLE;
36 break;
37 default:
38 n = LWS_CALLBACK_HTTP_WRITEABLE;
39 break;
40 }
41 lwsl_info("%s: %p (user=%p)\n", __func__, wsi, wsi->user_space);
42 return user_callback_handle_rxflow(wsi->protocol->callback, context,
43 wsi, (enum libwebsocket_callback_reasons) n,
44 wsi->user_space, NULL, 0);
45}
46
Andy Greend4741352014-04-03 07:36:41 +080047int
48lws_handle_POLLOUT_event(struct libwebsocket_context *context,
49 struct libwebsocket *wsi, struct libwebsocket_pollfd *pollfd)
50{
51 int n;
52 struct lws_tokens eff_buf;
Andy Green7df53c52014-10-22 15:37:28 +080053#ifdef LWS_USE_HTTP2
54 struct libwebsocket *wsi2;
55#endif
Andy Greend4741352014-04-03 07:36:41 +080056 int ret;
57 int m;
Andy Greend4741352014-04-03 07:36:41 +080058
59 /* pending truncated sends have uber priority */
60
61 if (wsi->truncated_send_len) {
Andy Greena1a24d22014-04-10 14:25:24 +080062 if (lws_issue_raw(wsi, wsi->truncated_send_malloc +
Andy Greend4741352014-04-03 07:36:41 +080063 wsi->truncated_send_offset,
Andy Greena1a24d22014-04-10 14:25:24 +080064 wsi->truncated_send_len) < 0) {
65 lwsl_info("lws_handle_POLLOUT_event signalling to close\n");
66 return -1;
67 }
Andy Greend4741352014-04-03 07:36:41 +080068 /* leave POLLOUT active either way */
69 return 0;
Andy Greenf4ffc1e2014-04-10 17:06:59 +080070 } else
71 if (wsi->state == WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE) {
72 lwsl_info("***** %x signalling to close in POLLOUT handler\n", wsi);
73 return -1; /* retry closing now */
74 }
Andy Green095d3032014-10-08 12:15:15 +080075#ifdef LWS_USE_HTTP2
Andy Green024eb6c2014-10-08 12:00:53 +080076 /* protocol packets are next */
77 if (wsi->pps) {
Andy Green095d3032014-10-08 12:15:15 +080078 lwsl_info("servicing pps %d\n", wsi->pps);
Andy Green024eb6c2014-10-08 12:00:53 +080079 switch (wsi->pps) {
80 case LWS_PPS_HTTP2_MY_SETTINGS:
81 case LWS_PPS_HTTP2_ACK_SETTINGS:
82 lws_http2_do_pps_send(context, wsi);
83 break;
84 default:
85 break;
86 }
87 wsi->pps = LWS_PPS_NONE;
88 libwebsocket_rx_flow_control(wsi, 1);
89
90 return 0; /* leave POLLOUT active */
91 }
Andy Green095d3032014-10-08 12:15:15 +080092#endif
Andy Green82bac6b2014-08-24 14:39:19 +080093 /* pending control packets have next priority */
94
Andy Green024eb6c2014-10-08 12:00:53 +080095 if (wsi->state == WSI_STATE_ESTABLISHED && wsi->u.ws.ping_payload_len) {
Andy Green82bac6b2014-08-24 14:39:19 +080096 n = libwebsocket_write(wsi,
97 &wsi->u.ws.ping_payload_buf[
98 LWS_SEND_BUFFER_PRE_PADDING],
99 wsi->u.ws.ping_payload_len,
100 LWS_WRITE_PONG);
101 if (n < 0)
102 return -1;
103 /* well he is sent, mark him done */
104 wsi->u.ws.ping_payload_len = 0;
105 /* leave POLLOUT active either way */
106 return 0;
107 }
Andy Greend4741352014-04-03 07:36:41 +0800108
Andy Green82bac6b2014-08-24 14:39:19 +0800109 /* if nothing critical, user can get the callback */
110
Andy Greend4741352014-04-03 07:36:41 +0800111 m = lws_ext_callback_for_each_active(wsi, LWS_EXT_CALLBACK_IS_WRITEABLE,
112 NULL, 0);
Andy Greend4741352014-04-03 07:36:41 +0800113#ifndef LWS_NO_EXTENSIONS
Andy Green66ecc252014-12-10 10:28:46 +0800114 if (!wsi->extension_data_pending)
Andy Greend4741352014-04-03 07:36:41 +0800115 goto user_service;
116#endif
117 /*
118 * check in on the active extensions, see if they
119 * had pending stuff to spill... they need to get the
120 * first look-in otherwise sequence will be disordered
121 *
122 * NULL, zero-length eff_buf means just spill pending
123 */
124
125 ret = 1;
126 while (ret == 1) {
127
128 /* default to nobody has more to spill */
129
130 ret = 0;
131 eff_buf.token = NULL;
132 eff_buf.token_len = 0;
133
134 /* give every extension a chance to spill */
135
136 m = lws_ext_callback_for_each_active(wsi,
137 LWS_EXT_CALLBACK_PACKET_TX_PRESEND,
138 &eff_buf, 0);
139 if (m < 0) {
140 lwsl_err("ext reports fatal error\n");
141 return -1;
142 }
143 if (m)
144 /*
145 * at least one extension told us he has more
146 * to spill, so we will go around again after
147 */
148 ret = 1;
149
150 /* assuming they gave us something to send, send it */
151
152 if (eff_buf.token_len) {
153 n = lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
154 eff_buf.token_len);
Andy Greena1a24d22014-04-10 14:25:24 +0800155 if (n < 0) {
156 lwsl_info("closing from POLLOUT spill\n");
Andy Greend4741352014-04-03 07:36:41 +0800157 return -1;
Andy Greena1a24d22014-04-10 14:25:24 +0800158 }
Andy Greend4741352014-04-03 07:36:41 +0800159 /*
160 * Keep amount spilled small to minimize chance of this
161 */
162 if (n != eff_buf.token_len) {
163 lwsl_err("Unable to spill ext %d vs %s\n",
164 eff_buf.token_len, n);
165 return -1;
166 }
167 } else
168 continue;
169
170 /* no extension has more to spill */
171
172 if (!ret)
173 continue;
174
175 /*
176 * There's more to spill from an extension, but we just sent
177 * something... did that leave the pipe choked?
178 */
179
180 if (!lws_send_pipe_choked(wsi))
181 /* no we could add more */
182 continue;
183
184 lwsl_info("choked in POLLOUT service\n");
185
186 /*
187 * Yes, he's choked. Leave the POLLOUT masked on so we will
188 * come back here when he is unchoked. Don't call the user
189 * callback to enforce ordering of spilling, he'll get called
190 * when we come back here and there's nothing more to spill.
191 */
192
193 return 0;
194 }
195#ifndef LWS_NO_EXTENSIONS
196 wsi->extension_data_pending = 0;
197
198user_service:
199#endif
200 /* one shot */
201
202 if (pollfd) {
Andy Green024eb6c2014-10-08 12:00:53 +0800203 if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) {
204 lwsl_info("failled at set pollfd\n");
Andy Greend4741352014-04-03 07:36:41 +0800205 return 1;
Andy Green024eb6c2014-10-08 12:00:53 +0800206 }
Andy Greena717df22014-04-11 13:14:37 +0800207
208 lws_libev_io(context, wsi, LWS_EV_STOP | LWS_EV_WRITE);
Andy Greend4741352014-04-03 07:36:41 +0800209 }
210
Andy Green7df53c52014-10-22 15:37:28 +0800211#ifdef LWS_USE_HTTP2
212 /*
213 * we are the 'network wsi' for potentially many muxed child wsi with
214 * no network connection of their own, who have to use us for all their
215 * network actions. So we use a round-robin scheme to share out the
216 * POLLOUT notifications to our children.
217 *
218 * But because any child could exhaust the socket's ability to take
219 * writes, we can only let one child get notified each time.
220 *
221 * In addition children may be closed / deleted / added between POLLOUT
222 * notifications, so we can't hold pointers
223 */
224
225 if (wsi->mode != LWS_CONNMODE_HTTP2_SERVING) {
226 lwsl_info("%s: non http2\n", __func__);
227 goto notify;
228 }
Andy Greend4741352014-04-03 07:36:41 +0800229
Andy Green7df53c52014-10-22 15:37:28 +0800230 wsi->u.http2.requested_POLLOUT = 0;
231 if (!wsi->u.http2.initialized) {
232 lwsl_info("pollout on uninitialized http2 conn\n");
233 return 0;
234 }
235
236 lwsl_info("%s: doing children\n", __func__);
237
238 wsi2 = wsi;
239 do {
240 wsi2 = wsi2->u.http2.next_child_wsi;
241 lwsl_info("%s: child %p\n", __func__, wsi2);
242 if (!wsi2)
243 continue;
244 if (!wsi2->u.http2.requested_POLLOUT)
245 continue;
246 wsi2->u.http2.requested_POLLOUT = 0;
247 if (lws_calllback_as_writeable(context, wsi2)) {
248 lwsl_debug("Closing POLLOUT child\n");
249 libwebsocket_close_and_free_session(context, wsi2,
250 LWS_CLOSE_STATUS_NOSTATUS);
251 }
252 wsi2 = wsi;
253 } while (wsi2 != NULL && !lws_send_pipe_choked(wsi));
254
255 lwsl_info("%s: completed\n", __func__);
256
257 return 0;
258notify:
259#endif
260 return lws_calllback_as_writeable(context, wsi);
Andy Greend4741352014-04-03 07:36:41 +0800261}
262
263
264
265int
266libwebsocket_service_timeout_check(struct libwebsocket_context *context,
267 struct libwebsocket *wsi, unsigned int sec)
268{
269 /*
270 * if extensions want in on it (eg, we are a mux parent)
271 * give them a chance to service child timeouts
272 */
273 if (lws_ext_callback_for_each_active(wsi, LWS_EXT_CALLBACK_1HZ, NULL, sec) < 0)
274 return 0;
275
276 if (!wsi->pending_timeout)
277 return 0;
278
279 /*
280 * if we went beyond the allowed time, kill the
281 * connection
282 */
283 if (sec > wsi->pending_timeout_limit) {
Andy Greenfe660b52014-04-10 11:03:22 +0800284 lwsl_info("TIMEDOUT WAITING on %d\n", wsi->pending_timeout);
Andy Greend4741352014-04-03 07:36:41 +0800285 libwebsocket_close_and_free_session(context,
286 wsi, LWS_CLOSE_STATUS_NOSTATUS);
287 return 1;
288 }
289
290 return 0;
291}
292
Andy Green024eb6c2014-10-08 12:00:53 +0800293int lws_rxflow_cache(struct libwebsocket *wsi, unsigned char *buf, int n, int len)
294{
295 /* his RX is flowcontrolled, don't send remaining now */
296 if (wsi->rxflow_buffer) {
297 /* rxflow while we were spilling prev rxflow */
298 lwsl_info("stalling in existing rxflow buf\n");
299 return 1;
300 }
301
302 /* a new rxflow, buffer it and warn caller */
303 lwsl_info("new rxflow input buffer len %d\n", len - n);
Alejandro Mery6ff28242014-12-04 23:59:35 +0100304 wsi->rxflow_buffer = lws_malloc(len - n);
Andy Green024eb6c2014-10-08 12:00:53 +0800305 wsi->rxflow_len = len - n;
306 wsi->rxflow_pos = 0;
307 memcpy(wsi->rxflow_buffer, buf + n, len - n);
308
309 return 0;
310}
311
Andy Greend4741352014-04-03 07:36:41 +0800312/**
313 * libwebsocket_service_fd() - Service polled socket with something waiting
314 * @context: Websocket context
315 * @pollfd: The pollfd entry describing the socket fd and which events
316 * happened.
317 *
318 * This function takes a pollfd that has POLLIN or POLLOUT activity and
319 * services it according to the state of the associated
320 * struct libwebsocket.
321 *
322 * The one call deals with all "service" that might happen on a socket
323 * including listen accepts, http files as well as websocket protocol.
324 *
325 * If a pollfd says it has something, you can just pass it to
326 * libwebsocket_serice_fd() whether it is a socket handled by lws or not.
327 * If it sees it is a lws socket, the traffic will be handled and
328 * pollfd->revents will be zeroed now.
329 *
330 * If the socket is foreign to lws, it leaves revents alone. So you can
331 * see if you should service yourself by checking the pollfd revents
332 * after letting lws try to service it.
333 */
334
335LWS_VISIBLE int
336libwebsocket_service_fd(struct libwebsocket_context *context,
337 struct libwebsocket_pollfd *pollfd)
338{
339 struct libwebsocket *wsi;
340 int n;
341 int m;
342 int listen_socket_fds_index = 0;
343 time_t now;
344 int timed_out = 0;
345 int our_fd = 0;
346 char draining_flow = 0;
347 int more;
348 struct lws_tokens eff_buf;
349
350 if (context->listen_service_fd)
Bud Davis229bfec2015-01-30 10:13:01 +0800351 listen_socket_fds_index = wsi_from_fd(context,context->listen_service_fd)->position_in_fds_table;
Andy Greend4741352014-04-03 07:36:41 +0800352
Bud Davis229bfec2015-01-30 10:13:01 +0800353 /*
Andy Greend4741352014-04-03 07:36:41 +0800354 * you can call us with pollfd = NULL to just allow the once-per-second
355 * global timeout checks; if less than a second since the last check
356 * it returns immediately then.
357 */
358
359 time(&now);
360
361 /* TODO: if using libev, we should probably use timeout watchers... */
362 if (context->last_timeout_check_s != now) {
363 context->last_timeout_check_s = now;
364
365 lws_plat_service_periodic(context);
366
367 /* global timeout check once per second */
368
369 if (pollfd)
370 our_fd = pollfd->fd;
371
372 for (n = 0; n < context->fds_count; n++) {
373 m = context->fds[n].fd;
Bud Davis229bfec2015-01-30 10:13:01 +0800374 wsi = wsi_from_fd(context,m);
Andy Greend4741352014-04-03 07:36:41 +0800375 if (!wsi)
376 continue;
377
378 if (libwebsocket_service_timeout_check(context, wsi, now))
379 /* he did time out... */
380 if (m == our_fd) {
381 /* it was the guy we came to service! */
382 timed_out = 1;
383 /* mark as handled */
Andy Green8ab2b5a2014-11-30 12:56:21 +0800384 if (pollfd)
385 pollfd->revents = 0;
Andy Greend4741352014-04-03 07:36:41 +0800386 }
387 }
388 }
389
390 /* the socket we came to service timed out, nothing to do */
391 if (timed_out)
392 return 0;
393
394 /* just here for timeout management? */
395 if (pollfd == NULL)
396 return 0;
397
398 /* no, here to service a socket descriptor */
Bud Davis229bfec2015-01-30 10:13:01 +0800399 wsi = wsi_from_fd(context,pollfd->fd);
Andy Greend4741352014-04-03 07:36:41 +0800400 if (wsi == NULL)
401 /* not lws connection ... leave revents alone and return */
402 return 0;
403
404 /*
405 * so that caller can tell we handled, past here we need to
406 * zero down pollfd->revents after handling
407 */
408
409 /*
410 * deal with listen service piggybacking
411 * every listen_service_modulo services of other fds, we
412 * sneak one in to service the listen socket if there's anything waiting
413 *
414 * To handle connection storms, as found in ab, if we previously saw a
415 * pending connection here, it causes us to check again next time.
416 */
417
418 if (context->listen_service_fd && pollfd !=
419 &context->fds[listen_socket_fds_index]) {
420 context->listen_service_count++;
421 if (context->listen_service_extraseen ||
422 context->listen_service_count ==
423 context->listen_service_modulo) {
424 context->listen_service_count = 0;
425 m = 1;
426 if (context->listen_service_extraseen > 5)
427 m = 2;
428 while (m--) {
429 /*
430 * even with extpoll, we prepared this
431 * internal fds for listen
432 */
433 n = lws_poll_listen_fd(&context->fds[listen_socket_fds_index]);
434 if (n > 0) { /* there's a conn waiting for us */
435 libwebsocket_service_fd(context,
436 &context->
437 fds[listen_socket_fds_index]);
438 context->listen_service_extraseen++;
439 } else {
440 if (context->listen_service_extraseen)
441 context->
442 listen_service_extraseen--;
443 break;
444 }
445 }
446 }
447
448 }
449
450 /* handle session socket closed */
451
452 if ((!(pollfd->revents & LWS_POLLIN)) &&
453 (pollfd->revents & LWS_POLLHUP)) {
454
455 lwsl_debug("Session Socket %p (fd=%d) dead\n",
456 (void *)wsi, pollfd->fd);
457
458 goto close_and_handled;
459 }
460
461 /* okay, what we came here to do... */
462
463 switch (wsi->mode) {
Andy Greend4741352014-04-03 07:36:41 +0800464 case LWS_CONNMODE_HTTP_SERVING:
465 case LWS_CONNMODE_HTTP_SERVING_ACCEPTED:
466 case LWS_CONNMODE_SERVER_LISTENER:
467 case LWS_CONNMODE_SSL_ACK_PENDING:
468 n = lws_server_socket_service(context, wsi, pollfd);
Andy Greena1a24d22014-04-10 14:25:24 +0800469 if (n < 0)
470 goto close_and_handled;
Andy Greend4741352014-04-03 07:36:41 +0800471 goto handled;
Andy Greend4741352014-04-03 07:36:41 +0800472
473 case LWS_CONNMODE_WS_SERVING:
474 case LWS_CONNMODE_WS_CLIENT:
Andy Green024eb6c2014-10-08 12:00:53 +0800475 case LWS_CONNMODE_HTTP2_SERVING:
Andy Greend4741352014-04-03 07:36:41 +0800476
477 /* the guy requested a callback when it was OK to write */
478
479 if ((pollfd->revents & LWS_POLLOUT) &&
Andy Green024eb6c2014-10-08 12:00:53 +0800480 (wsi->state == WSI_STATE_ESTABLISHED || wsi->state == WSI_STATE_HTTP2_ESTABLISHED || wsi->state == WSI_STATE_HTTP2_ESTABLISHED_PRE_SETTINGS ||
Andy Greena1a24d22014-04-10 14:25:24 +0800481 wsi->state == WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE) &&
Andy Green8e18fe32014-04-06 12:40:16 +0100482 lws_handle_POLLOUT_event(context, wsi, pollfd)) {
Andy Greend4741352014-04-03 07:36:41 +0800483 lwsl_info("libwebsocket_service_fd: closing\n");
484 goto close_and_handled;
485 }
486
Andy Green024eb6c2014-10-08 12:00:53 +0800487 if (wsi->rxflow_buffer &&
488 (wsi->rxflow_change_to & LWS_RXFLOW_ALLOW)) {
Andy Greend4741352014-04-03 07:36:41 +0800489 lwsl_info("draining rxflow\n");
490 /* well, drain it */
Andy Green024eb6c2014-10-08 12:00:53 +0800491 eff_buf.token = (char *)wsi->rxflow_buffer +
492 wsi->rxflow_pos;
493 eff_buf.token_len = wsi->rxflow_len - wsi->rxflow_pos;
Andy Greend4741352014-04-03 07:36:41 +0800494 draining_flow = 1;
495 goto drain;
496 }
497
498 /* any incoming data ready? */
499
500 if (!(pollfd->revents & LWS_POLLIN))
501 break;
502
Andy Green609ec852014-10-09 08:29:22 +0800503 eff_buf.token_len = lws_ssl_capable_read(context, wsi,
Andy Greend4741352014-04-03 07:36:41 +0800504 context->service_buffer,
Andy Green78f266a2014-04-05 16:48:48 +0100505 sizeof(context->service_buffer));
506 switch (eff_buf.token_len) {
507 case 0:
508 lwsl_info("service_fd: closing due to 0 length read\n");
509 goto close_and_handled;
AndyMcG7ab4ede2014-07-05 11:25:11 +0800510 case LWS_SSL_CAPABLE_MORE_SERVICE:
511 lwsl_info("SSL Capable more service\n");
Andy Greend4741352014-04-03 07:36:41 +0800512 n = 0;
513 goto handled;
AndyMcG7ab4ede2014-07-05 11:25:11 +0800514 case LWS_SSL_CAPABLE_ERROR:
515 lwsl_info("Closing when error\n");
Andy Greend4741352014-04-03 07:36:41 +0800516 goto close_and_handled;
517 }
518
519 /*
520 * give any active extensions a chance to munge the buffer
521 * before parse. We pass in a pointer to an lws_tokens struct
522 * prepared with the default buffer and content length that's in
523 * there. Rather than rewrite the default buffer, extensions
524 * that expect to grow the buffer can adapt .token to
525 * point to their own per-connection buffer in the extension
526 * user allocation. By default with no extensions or no
527 * extension callback handling, just the normal input buffer is
528 * used then so it is efficient.
529 */
530
531 eff_buf.token = (char *)context->service_buffer;
532drain:
533
534 do {
535
536 more = 0;
537
538 m = lws_ext_callback_for_each_active(wsi,
539 LWS_EXT_CALLBACK_PACKET_RX_PREPARSE, &eff_buf, 0);
540 if (m < 0)
541 goto close_and_handled;
542 if (m)
543 more = 1;
544
545 /* service incoming data */
546
547 if (eff_buf.token_len) {
548 n = libwebsocket_read(context, wsi,
549 (unsigned char *)eff_buf.token,
550 eff_buf.token_len);
551 if (n < 0) {
552 /* we closed wsi */
553 n = 0;
554 goto handled;
555 }
556 }
557
558 eff_buf.token = NULL;
559 eff_buf.token_len = 0;
560 } while (more);
561
Andy Green024eb6c2014-10-08 12:00:53 +0800562 if (draining_flow && wsi->rxflow_buffer &&
563 wsi->rxflow_pos == wsi->rxflow_len) {
Andy Greend4741352014-04-03 07:36:41 +0800564 lwsl_info("flow buffer: drained\n");
Alejandro Meryac3ec392014-12-05 00:09:20 +0100565 lws_free2(wsi->rxflow_buffer);
Andy Greend4741352014-04-03 07:36:41 +0800566 /* having drained the rxflow buffer, can rearm POLLIN */
Andy Greena3493672014-12-10 10:24:33 +0800567#ifdef LWS_NO_SERVER
568 n =
569#endif
Andy Green2c8161c2014-11-30 12:29:04 +0800570 _libwebsocket_rx_flow_control(wsi); /* n ignored, needed for NO_SERVER case */
Andy Greend4741352014-04-03 07:36:41 +0800571 }
572
Andy Greend4741352014-04-03 07:36:41 +0800573 break;
574
575 default:
576#ifdef LWS_NO_CLIENT
577 break;
578#else
579 n = lws_client_socket_service(context, wsi, pollfd);
580 goto handled;
581#endif
582 }
583
584 n = 0;
585 goto handled;
586
587close_and_handled:
AndyMcG7ab4ede2014-07-05 11:25:11 +0800588 lwsl_debug("Close and handled\n");
Andy Greend4741352014-04-03 07:36:41 +0800589 libwebsocket_close_and_free_session(context, wsi,
590 LWS_CLOSE_STATUS_NOSTATUS);
591 n = 1;
592
593handled:
594 pollfd->revents = 0;
595 return n;
596}
597
598/**
599 * libwebsocket_service() - Service any pending websocket activity
600 * @context: Websocket context
601 * @timeout_ms: Timeout for poll; 0 means return immediately if nothing needed
602 * service otherwise block and service immediately, returning
603 * after the timeout if nothing needed service.
604 *
605 * This function deals with any pending websocket traffic, for three
606 * kinds of event. It handles these events on both server and client
607 * types of connection the same.
608 *
609 * 1) Accept new connections to our context's server
610 *
611 * 2) Call the receive callback for incoming frame data received by
612 * server or client connections.
613 *
614 * You need to call this service function periodically to all the above
615 * functions to happen; if your application is single-threaded you can
616 * just call it in your main event loop.
617 *
618 * Alternatively you can fork a new process that asynchronously handles
619 * calling this service in a loop. In that case you are happy if this
620 * call blocks your thread until it needs to take care of something and
621 * would call it with a large nonzero timeout. Your loop then takes no
622 * CPU while there is nothing happening.
623 *
624 * If you are calling it in a single-threaded app, you don't want it to
625 * wait around blocking other things in your loop from happening, so you
626 * would call it with a timeout_ms of 0, so it returns immediately if
627 * nothing is pending, or as soon as it services whatever was pending.
628 */
629
630LWS_VISIBLE int
631libwebsocket_service(struct libwebsocket_context *context, int timeout_ms)
632{
633 return lws_plat_service(context, timeout_ms);
634}
635