introduce-external-poll-callbacks.patch
authorAndy Green <andy.green@linaro.org>
Sat, 12 Feb 2011 13:14:11 +0000 (13:14 +0000)
committerAndy Green <andy.green@linaro.org>
Sat, 12 Feb 2011 13:14:11 +0000 (13:14 +0000)
Signed-off-by: Andy Green <andy.green@linaro.org>
lib/client-handshake.c
lib/libwebsockets.c
lib/libwebsockets.h
libwebsockets-api-doc.html

index e3a6efc..fd786cd 100644 (file)
@@ -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;
 
index 83505c8..49913b7 100644 (file)
@@ -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;
        }
 
index d15c2c7..5a870d7 100644 (file)
@@ -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 {
index 9e5f27e..40a0c0b 100644 (file)
@@ -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.
 </blockquote>
 <hr>
-<h2>libwebsocket_callback_on_writable - Request a callback when this socket becomes able to be written to without blocking</h2>
+<h2>libwebsocket_callback_on_writable - Request a callback when this socket becomes able to be written to without blocking *</h2>
 <i>int</i>
 <b>libwebsocket_callback_on_writable</b>
 (<i>struct libwebsocket *</i> <b>wsi</b>)
@@ -87,13 +87,6 @@ nothing is pending, or as soon as it services whatever was pending.
 <dt><b>wsi</b>
 <dd>Websocket connection instance to get callback for
 </dl>
-<h3>Description</h3>
-<blockquote>
-<p>
-This only works for internal <b>poll</b> management, (ie, calling the libwebsocket
-service loop, you will have to make your own arrangements if your <b>poll</b>
-loop is managed externally.
-</blockquote>
 <hr>
 <h2>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.</h2>
 <i>int</i>
@@ -104,13 +97,6 @@ loop is managed externally.
 <dt><b>protocol</b>
 <dd>Protocol whose connections will get callbacks
 </dl>
-<h3>Description</h3>
-<blockquote>
-<p>
-This only works for internal <b>poll</b> management, (ie, calling the libwebsocket
-service loop, you will have to make your own arrangements if your <b>poll</b>
-loop is managed externally.
-</blockquote>
 <hr>
 <h2>libwebsocket_get_socket_fd - returns the socket file descriptor</h2>
 <i>int</i>
@@ -144,10 +130,6 @@ You will not need this unless you are doing something special
 <p>
 If the output side of a server process becomes choked, this allows flow
 control for the input side.
-<p>
-This only works for internal <b>poll</b> management, (ie, calling the libwebsocket
-service loop, you will have to make your own arrangements if your <b>poll</b>
-loop is managed externally.
 </blockquote>
 <hr>
 <h2>libwebsocket_canonical_hostname - returns this host's hostname</h2>