From 3221f92b1e7cac445150d97ce2f13e49b6a7ffeb Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 12 Feb 2011 13:14:11 +0000 Subject: [PATCH] introduce-external-poll-callbacks.patch Signed-off-by: Andy Green --- lib/client-handshake.c | 6 +++ lib/libwebsockets.c | 100 ++++++++++++++++++++++++++++++++------------- lib/libwebsockets.h | 8 +++- libwebsockets-api-doc.html | 20 +-------- 4 files changed, 86 insertions(+), 48 deletions(-) diff --git a/lib/client-handshake.c b/lib/client-handshake.c index e3a6efc..fd786cd 100644 --- a/lib/client-handshake.c +++ b/lib/client-handshake.c @@ -567,6 +567,12 @@ check_accept: this->fds[this->fds_count].revents = 0; this->fds[this->fds_count++].events = POLLIN; + /* external POLL support via protocol 0 */ + this->protocols[0].callback(wsi, + LWS_CALLBACK_ADD_POLL_FD, + (void *)(long)wsi->sock, NULL, POLLIN); + + wsi->state = WSI_STATE_ESTABLISHED; wsi->mode = LWS_CONNMODE_WS_CLIENT; diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index 83505c8..49913b7 100644 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -182,7 +182,7 @@ libwebsocket_service_fd(struct libwebsocket_context *this, } if (this->fds_count >= MAX_CLIENTS) { - fprintf(stderr, "too busy"); + fprintf(stderr, "too busy to accept new client\n"); close(accept_fd); break; } @@ -271,7 +271,6 @@ libwebsocket_service_fd(struct libwebsocket_context *this, insert_wsi(this, new_wsi); - /* * make sure NO events are seen yet on this new socket * (otherwise we inherit old fds[client].revents from @@ -282,6 +281,11 @@ libwebsocket_service_fd(struct libwebsocket_context *this, this->fds[this->fds_count].events = POLLIN; this->fds[this->fds_count++].fd = accept_fd; + /* external POLL support via protocol 0 */ + this->protocols[0].callback(new_wsi, + LWS_CALLBACK_ADD_POLL_FD, + (void *)(long)accept_fd, NULL, POLLIN); + break; case LWS_CONNMODE_BROADCAST_PROXY_LISTENER: @@ -302,7 +306,8 @@ libwebsocket_service_fd(struct libwebsocket_context *this, } if (this->fds_count >= MAX_CLIENTS) { - fprintf(stderr, "too busy"); + fprintf(stderr, "too busy to accept new broadcast " + "proxy client\n"); close(accept_fd); break; } @@ -325,6 +330,11 @@ libwebsocket_service_fd(struct libwebsocket_context *this, this->fds[this->fds_count].events = POLLIN; this->fds[this->fds_count++].fd = accept_fd; + /* external POLL support via protocol 0 */ + this->protocols[0].callback(new_wsi, + LWS_CALLBACK_ADD_POLL_FD, + (void *)(long)accept_fd, NULL, POLLIN); + break; case LWS_CONNMODE_BROADCAST_PROXY: @@ -348,6 +358,11 @@ libwebsocket_service_fd(struct libwebsocket_context *this, pollfd->events &= ~POLLOUT; + /* external POLL support via protocol 0 */ + this->protocols[0].callback(wsi, + LWS_CALLBACK_CLEAR_MODE_POLL_FD, + (void *)(long)wsi->sock, NULL, POLLOUT); + wsi->protocol->callback(wsi, LWS_CALLBACK_CLIENT_WRITEABLE, wsi->user_space, @@ -428,6 +443,11 @@ libwebsocket_service_fd(struct libwebsocket_context *this, pollfd->events &= ~POLLOUT; + /* external POLL support via protocol 0 */ + this->protocols[0].callback(wsi, + LWS_CALLBACK_CLEAR_MODE_POLL_FD, + (void *)(long)wsi->sock, NULL, POLLOUT); + wsi->protocol->callback(wsi, LWS_CALLBACK_CLIENT_WRITEABLE, wsi->user_space, @@ -481,6 +501,12 @@ nuke_this: n = this->fds_count; } + /* external POLL support via protocol 0 */ + this->protocols[0].callback(wsi, + LWS_CALLBACK_DEL_POLL_FD, + (void *)(long)pollfd->fd, NULL, 0); + + break; } @@ -583,6 +609,8 @@ libwebsocket_service(struct libwebsocket_context *this, int timeout_ms) /* wait for something to need service */ n = poll(this->fds, this->fds_count, timeout_ms); + if (n == 0) /* poll timeout */ + return 0; if (n < 0 || this->fds[0].revents & (POLLERR | POLLHUP)) { /* @@ -590,8 +618,6 @@ libwebsocket_service(struct libwebsocket_context *this, int timeout_ms) */ return 1; } - if (n == 0) /* poll timeout */ - return 0; /* handle accept on listening socket? */ @@ -606,11 +632,7 @@ libwebsocket_service(struct libwebsocket_context *this, int timeout_ms) * libwebsocket_callback_on_writable() - Request a callback when this socket * becomes able to be written to without * blocking - * - * This only works for internal poll() management, (ie, calling the libwebsocket - * service loop, you will have to make your own arrangements if your poll() - * loop is managed externally. - * + * * * @wsi: Websocket connection instance to get callback for */ @@ -623,11 +645,14 @@ libwebsocket_callback_on_writable(struct libwebsocket *wsi) for (n = 0; n < this->fds_count; n++) if (this->fds[n].fd == wsi->sock) { this->fds[n].events |= POLLOUT; - return 0; + n = this->fds_count; } - fprintf(stderr, "libwebsocket_callback_on_writable " - "didn't find socket\n"); + /* external POLL support via protocol 0 */ + this->protocols[0].callback(wsi, + LWS_CALLBACK_SET_MODE_POLL_FD, + (void *)(long)wsi->sock, NULL, POLLOUT); + return 1; } @@ -637,10 +662,6 @@ libwebsocket_callback_on_writable(struct libwebsocket *wsi) * becomes possible to write to each socket without * blocking in turn. * - * This only works for internal poll() management, (ie, calling the libwebsocket - * service loop, you will have to make your own arrangements if your poll() - * loop is managed externally. - * * @protocol: Protocol whose connections will get callbacks */ @@ -689,10 +710,6 @@ libwebsocket_get_socket_fd(struct libwebsocket *wsi) * If the output side of a server process becomes choked, this allows flow * control for the input side. * - * This only works for internal poll() management, (ie, calling the libwebsocket - * service loop, you will have to make your own arrangements if your poll() - * loop is managed externally. - * * @wsi: Websocket connection instance to get callback for * @enable: 0 = disable read servicing for this connection, 1 = enable */ @@ -713,6 +730,18 @@ libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable) return 0; } + if (enable) + /* external POLL support via protocol 0 */ + this->protocols[0].callback(wsi, + LWS_CALLBACK_SET_MODE_POLL_FD, + (void *)(long)wsi->sock, NULL, POLLIN); + else + /* external POLL support via protocol 0 */ + this->protocols[0].callback(wsi, + LWS_CALLBACK_CLEAR_MODE_POLL_FD, + (void *)(long)wsi->sock, NULL, POLLIN); + + fprintf(stderr, "libwebsocket_callback_on_writable " "unable to find socket\n"); return 1; @@ -1024,6 +1053,12 @@ libwebsocket_create_context(int port, this->fds[this->fds_count].fd = sockfd; this->fds[this->fds_count++].events = POLLIN; + + /* external POLL support via protocol 0 */ + this->protocols[0].callback(wsi, + LWS_CALLBACK_ADD_POLL_FD, + (void *)(long)sockfd, NULL, POLLIN); + } /* drop any root privs for this process */ @@ -1094,7 +1129,13 @@ libwebsocket_create_context(int port, this->fds[this->fds_count].fd = fd; this->fds[this->fds_count].events = POLLIN; + this->fds[this->fds_count].revents = 0; this->fds_count++; + + /* external POLL support via protocol 0 */ + this->protocols[0].callback(wsi, + LWS_CALLBACK_ADD_POLL_FD, + (void *)(long)fd, NULL, POLLIN); } return this; @@ -1116,10 +1157,10 @@ libwebsocket_create_context(int port, int libwebsockets_fork_service_loop(struct libwebsocket_context *this) { - int client; int fd; struct sockaddr_in cli_addr; int n; + int p; n = fork(); if (n < 0) @@ -1129,7 +1170,12 @@ libwebsockets_fork_service_loop(struct libwebsocket_context *this) /* main process context */ - for (client = 1; client < this->count_protocols + 1; client++) { + /* + * set up the proxy sockets to allow broadcast from + * service process context + */ + + for (p = 0; p < this->count_protocols; p++) { fd = socket(AF_INET, SOCK_STREAM, 0); if (fd < 0) { fprintf(stderr, "Unable to create socket\n"); @@ -1137,22 +1183,20 @@ libwebsockets_fork_service_loop(struct libwebsocket_context *this) } cli_addr.sin_family = AF_INET; cli_addr.sin_port = htons( - this->protocols[client - 1].broadcast_socket_port); + this->protocols[p].broadcast_socket_port); cli_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); n = connect(fd, (struct sockaddr *)&cli_addr, sizeof cli_addr); if (n < 0) { fprintf(stderr, "Unable to connect to " "broadcast socket %d, %s\n", - client, strerror(errno)); + n, strerror(errno)); return -1; } - this->protocols[client - 1].broadcast_socket_user_fd = - fd; + this->protocols[p].broadcast_socket_user_fd = fd; } - return 0; } diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index d15c2c7..5a870d7 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -40,7 +40,13 @@ enum libwebsocket_callback_reasons { LWS_CALLBACK_CLIENT_RECEIVE_PONG, LWS_CALLBACK_CLIENT_WRITEABLE, LWS_CALLBACK_HTTP, - LWS_CALLBACK_BROADCAST + LWS_CALLBACK_BROADCAST, + + /* external poll() management support */ + LWS_CALLBACK_ADD_POLL_FD, + LWS_CALLBACK_DEL_POLL_FD, + LWS_CALLBACK_SET_MODE_POLL_FD, + LWS_CALLBACK_CLEAR_MODE_POLL_FD, }; enum libwebsocket_write_protocol { diff --git a/libwebsockets-api-doc.html b/libwebsockets-api-doc.html index 9e5f27e..40a0c0b 100644 --- a/libwebsockets-api-doc.html +++ b/libwebsockets-api-doc.html @@ -78,7 +78,7 @@ would call it with a timeout_ms of 0, so it returns immediately if nothing is pending, or as soon as it services whatever was pending.
-

libwebsocket_callback_on_writable - Request a callback when this socket becomes able to be written to without blocking

+

libwebsocket_callback_on_writable - Request a callback when this socket becomes able to be written to without blocking *

int libwebsocket_callback_on_writable (struct libwebsocket * wsi) @@ -87,13 +87,6 @@ nothing is pending, or as soon as it services whatever was pending.
wsi
Websocket connection instance to get callback for -

Description

-
-

-This only works for internal poll management, (ie, calling the libwebsocket -service loop, you will have to make your own arrangements if your poll -loop is managed externally. -


libwebsocket_callback_on_writable_all_protocol - Request a callback for all connections using the given protocol when it becomes possible to write to each socket without blocking in turn.

int @@ -104,13 +97,6 @@ loop is managed externally.
protocol
Protocol whose connections will get callbacks -

Description

-
-

-This only works for internal poll management, (ie, calling the libwebsocket -service loop, you will have to make your own arrangements if your poll -loop is managed externally. -


libwebsocket_get_socket_fd - returns the socket file descriptor

int @@ -144,10 +130,6 @@ You will not need this unless you are doing something special

If the output side of a server process becomes choked, this allows flow control for the input side. -

-This only works for internal poll management, (ie, calling the libwebsocket -service loop, you will have to make your own arrangements if your poll -loop is managed externally.


libwebsocket_canonical_hostname - returns this host's hostname

-- 2.7.4