clean--fix-sigpipe.patch
authorAndy Green <andy@warmcat.com>
Sun, 23 Jan 2011 16:50:33 +0000 (16:50 +0000)
committerAndy Green <andy@warmcat.com>
Sun, 23 Jan 2011 16:50:33 +0000 (16:50 +0000)
Signed-off-by: Andy Green <andy@warmcat.com>
lib/client-handshake.c
lib/handshake.c
lib/libwebsockets.c
lib/libwebsockets.h
lib/parsers.c
lib/private-libwebsockets.h
libwebsockets-api-doc.html
test-server/test-client.c
test-server/test-server.c

index 1ef80f4..64f72cb 100644 (file)
@@ -89,13 +89,13 @@ libwebsocket_client_connect(struct libwebsocket_context *clients,
                                         "61AC5F19-FBBA-4540-B96F-6561F1AB40A8";
        char pkt[1024];
        char *p = &pkt[0];
-       const char * pc;
+       const char *pc;
        int len;
        int okay = 0;
        struct libwebsocket *wsi;
        int n;
 
-       wsi = malloc(sizeof (struct libwebsocket));
+       wsi = malloc(sizeof(struct libwebsocket));
        if (wsi == NULL)
                return NULL;
 
@@ -123,7 +123,7 @@ libwebsocket_client_connect(struct libwebsocket_context *clients,
        }
 
        wsi->sock = socket(AF_INET, SOCK_STREAM, 0);
-       
+
        if (wsi->sock < 0) {
                fprintf(stderr, "Unable to open socket\n");
                goto bail1;
@@ -139,11 +139,11 @@ libwebsocket_client_connect(struct libwebsocket_context *clients,
                                              sizeof(struct sockaddr)) == -1)  {
                fprintf(stderr, "Connect failed");
                goto bail1;
-        }
+       }
 
-        /*
-         * create the random key
-         */
+       /*
+        * create the random key
+        */
 
        fd = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY);
        if (fd < 1) {
@@ -160,7 +160,7 @@ libwebsocket_client_connect(struct libwebsocket_context *clients,
        }
        close(fd);
 
-       lws_b64_encode_string(hash, 16, key_b64, sizeof key_b64);       
+       lws_b64_encode_string(hash, 16, key_b64, sizeof key_b64);
 
        /*
         * 04 example client handshake
@@ -283,7 +283,7 @@ libwebsocket_client_connect(struct libwebsocket_context *clients,
                                " Upgrade header '%s'\n",
                                      wsi->utf8_token[WSI_TOKEN_UPGRADE].token);
                goto bail2;
-       }       
+       }
 
        strtolower(wsi->utf8_token[WSI_TOKEN_CONNECTION].token);
        if (strcmp(wsi->utf8_token[WSI_TOKEN_CONNECTION].token, "upgrade")) {
index 842b764..d6928d7 100644 (file)
@@ -376,7 +376,7 @@ handshake_04(struct libwebsocket *wsi)
        m += nonce_len;
        strcpy(m, websocket_magic_guid_04_masking);
        m += strlen(websocket_magic_guid_04_masking);
-       
+
        SHA1((unsigned char *)mask_summing_buf, m - mask_summing_buf,
                                                           wsi->masking_key_04);
 
@@ -564,9 +564,9 @@ libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len)
                        return 0;
                }
 
-
                if (libwebsocket_interpret_incoming_packet(wsi, buf, len) < 0)
                        goto bail;
+
                break;
        default:
                break;
@@ -576,5 +576,6 @@ libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len)
 
 bail:
        libwebsocket_close_and_free_session(wsi);
+
        return -1;
 }
index aae6690..1c4bd17 100644 (file)
@@ -86,7 +86,8 @@ libwebsocket_poll_connections(struct libwebsocket_context *this)
                if (this->fds[client].revents & (POLLERR | POLLHUP)) {
 
                        debug("Session Socket %d %p (fd=%d) dead\n",
-                                 client, this->wsi[client], this->fds[client]);
+                               client, (void *)this->wsi[client],
+                                                         this->fds[client].fd);
 
                        libwebsocket_close_and_free_session(this->wsi[client]);
                        goto nuke_this;
@@ -132,7 +133,7 @@ libwebsocket_poll_connections(struct libwebsocket_context *this)
                                        continue;
 
                                /* only to clients connected to us */
-                               
+
                                if (wsi->client_mode)
                                        continue;
 
@@ -174,9 +175,9 @@ libwebsocket_poll_connections(struct libwebsocket_context *this)
 
                /* service incoming data */
 
-               if (libwebsocket_read(this->wsi[client], buf, n) >= 0)
+               n = libwebsocket_read(this->wsi[client], buf, n);
+               if (n >= 0)
                        continue;
-
                /*
                 * it closed and nuked wsi[client], so remove the
                 * socket handle and wsi from our service list
@@ -184,19 +185,82 @@ libwebsocket_poll_connections(struct libwebsocket_context *this)
 nuke_this:
 
                debug("nuking wsi %p, fsd_count = %d\n",
-                                       this->wsi[client], this->fds_count - 1);
+                               (void *)this->wsi[client], this->fds_count - 1);
 
                this->fds_count--;
                for (n = client; n < this->fds_count; n++) {
                        this->fds[n] = this->fds[n + 1];
                        this->wsi[n] = this->wsi[n + 1];
                }
-               break;
+
+               return 0;
+
        }
 
        return 0;
 }
 
+/**
+ * libwebsocket_context_destroy() - Destroy the websocket context
+ * @this:      Websocket context
+ *
+ *     This function closes any active connections and then frees the
+ *     context.  After calling this, any further use of the context is
+ *     undefined.
+ */
+void
+libwebsocket_context_destroy(struct libwebsocket_context *this)
+{
+       int client;
+
+       /* close listening skt and per-protocol broadcast sockets */
+       for (client = 0; client < this->fds_count; client++)
+               libwebsocket_close_and_free_session(this->wsi[client]);
+
+#ifdef LWS_OPENSSL_SUPPORT
+       if (ssl_ctx)
+               SSL_CTX_free(ssl_ctx);
+#endif
+
+       if (this)
+               free(this);
+}
+
+/**
+ * libwebsocket_service() - Service any pending websocket activity
+ * @this:      Websocket context
+ * @timeout_ms:        Timeout for poll; 0 means return immediately if nothing needed
+ *             service otherwise block and service immediately, returning
+ *             after the timeout if nothing needed service.
+ *
+ *     This function deals with any pending websocket traffic, for three
+ *     kinds of event.  It handles these events on both server and client
+ *     types of connection the same.
+ *
+ *     1) Accept new connections to our context's server
+ *
+ *     2) Perform pending broadcast writes initiated from other forked
+ *        processes (effectively serializing asynchronous broadcasts)
+ *
+ *     3) Call the receive callback for incoming frame data received by
+ *         server or client connections.
+ *
+ *     You need to call this service function periodically to all the above
+ *     functions to happen; if your application is single-threaded you can
+ *     just call it in your main event loop.
+ *
+ *     Alternatively you can fork a new process that asynchronously handles
+ *     calling this service in a loop.  In that case you are happy if this
+ *     call blocks your thread until it needs to take care of something and
+ *     would call it with a large nonzero timeout.  Your loop then takes no
+ *     CPU while there is nothing happening.
+ *
+ *     If you are calling it in a single-threaded app, you don't want it to
+ *     wait around blocking other things in your loop from happening, so you
+ *     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.
+ */
+
 
 int
 libwebsocket_service(struct libwebsocket_context *this, int timeout_ms)
@@ -218,7 +282,7 @@ libwebsocket_service(struct libwebsocket_context *this, int timeout_ms)
                n = poll(this->fds, this->fds_count, timeout_ms);
        else
                n = poll(&this->fds[1], this->fds_count - 1, timeout_ms);
-       
+
 
        if (n < 0 || this->fds[0].revents & (POLLERR | POLLHUP)) {
                fprintf(stderr, "Listen Socket dead\n");
@@ -369,6 +433,8 @@ fill_in_fds:
 
 fatal:
 
+       fprintf(stderr, "service hits fatal\n");
+
        /* close listening skt and per-protocol broadcast sockets */
        for (client = 0; client < this->fds_count; client++)
                close(this->fds[0].fd);
@@ -376,7 +442,6 @@ fatal:
 #ifdef LWS_OPENSSL_SUPPORT
        SSL_CTX_free(ssl_ctx);
 #endif
-       kill(0, SIGTERM);
 
        if (this)
                free(this);
@@ -392,12 +457,12 @@ fatal:
 /**
  * libwebsocket_create_context() - Create the websocket handler
  * @port:      Port to listen on... you can use 0 to suppress listening on
- *             any port, that's what you want if you are not running a
- *             websocket server at all but just using it as a client
+ *             any port, that's what you want if you are not running a
+ *             websocket server at all but just using it as a client
  * @protocols: Array of structures listing supported protocols and a protocol-
  *             specific callback for each one.  The list is ended with an
  *             entry that has a NULL callback pointer.
- *             It's not const because we write the owning_server member
+ *             It's not const because we write the owning_server member
  * @ssl_cert_filepath: If libwebsockets was compiled to use ssl, and you want
  *                     to listen using SSL, set to the filepath to fetch the
  *                     server cert from, otherwise NULL for unencrypted
@@ -644,10 +709,10 @@ libwebsocket_create_context(int port,
 /**
  * libwebsockets_fork_service_loop() - Optional helper function forks off
  *                               a process for the websocket server loop.
- *                             You don't have to use this but if not, you
- *                             have to make sure you are calling
- *                             libwebsocket_service periodically to service
- *                             the websocket traffic
+ *                             You don't have to use this but if not, you
+ *                             have to make sure you are calling
+ *                             libwebsocket_service periodically to service
+ *                             the websocket traffic
  * @this:      server context returned by creation function
  */
 
@@ -798,7 +863,7 @@ libwebsockets_broadcast(const struct libwebsocket_protocols *protocol,
         * set up when the websocket server initializes
         */
 
-       n = send(protocol->broadcast_socket_user_fd, buf, len, 0);
+       n = send(protocol->broadcast_socket_user_fd, buf, len, MSG_NOSIGNAL);
 
        return n;
 }
index b6d7335..57ab481 100644 (file)
@@ -59,11 +59,11 @@ struct libwebsocket_context;
  *
  *     This callback is the way the user controls what is served.  All the
  *     protocol detail is hidden and handled by the library.
- * 
+ *
  *     For each connection / session there is user data allocated that is
  *     pointed to by "user".  You set the size of this user data area when
  *     the library is initialized with libwebsocket_create_server.
- * 
+ *
  *     You get an opportunity to initialize user data when called back with
  *     LWS_CALLBACK_ESTABLISHED reason.
  *
@@ -77,45 +77,45 @@ struct libwebsocket_context;
  *     LWS_CALLBACK_RECEIVE: data has appeared for the server, it can be
  *                             found at *in and is len bytes long
  *
- *     LWS_CALLBACK_HTTP: an http request has come from a client that is not
+ *     LWS_CALLBACK_HTTP: an http request has come from a client that is not
  *                             asking to upgrade the connection to a websocket
  *                             one.  This is a chance to serve http content,
  *                             for example, to send a script to the client
  *                             which will then open the websockets connection.
- *                             @in points to the URI path requested and 
+ *                             @in points to the URI path requested and
  *                             libwebsockets_serve_http_file() makes it very
  *                             simple to send back a file to the client.
  */
-extern int callback(struct libwebsocket * wsi,
-                        enum libwebsocket_callback_reasons reason, void * user,
+extern int callback(struct libwebsocket *wsi,
+                        enum libwebsocket_callback_reasons reason, void *user,
                                                          void *in, size_t len);
 
 /**
- * struct libwebsocket_protocols -     List of protocols and handlers server
- *                                     supports.
+ * struct libwebsocket_protocols -     List of protocols and handlers server
+ *                                     supports.
  * @name:      Protocol name that must match the one given in the client
- *             Javascript new WebSocket(url, 'protocol') name
+ *             Javascript new WebSocket(url, 'protocol') name
  * @callback:  The service callback used for this protocol.  It allows the
- *             service action for an entire protocol to be encapsulated in
- *             the protocol-specific callback
+ *             service action for an entire protocol to be encapsulated in
+ *             the protocol-specific callback
  * @per_session_data_size:     Each new connection using this protocol gets
- *             this much memory allocated on connection establishment and
- *             freed on connection takedown.  A pointer to this per-connection
- *             allocation is passed into the callback in the 'user' parameter
+ *             this much memory allocated on connection establishment and
+ *             freed on connection takedown.  A pointer to this per-connection
+ *             allocation is passed into the callback in the 'user' parameter
  * @owning_server:     the server init call fills in this opaque pointer when
- *             registering this protocol with the server.
+ *             registering this protocol with the server.
  * @broadcast_socket_port: the server init call fills this in with the
- *             localhost port number used to forward broadcasts for this
- *             protocol
+ *             localhost port number used to forward broadcasts for this
+ *             protocol
  * @broadcast_socket_user_fd:  the server init call fills this in ... the main()
- *             process context can write to this socket to perform broadcasts
- *             (use the libwebsockets_broadcast() api to do this instead,
- *             it works from any process context)
+ *             process context can write to this socket to perform broadcasts
+ *             (use the libwebsockets_broadcast() api to do this instead,
+ *             it works from any process context)
  * @protocol_index: which protocol we are starting from zero
  *
- *     This structure represents one protocol supported by the server.  An
- *     array of these structures is passed to libwebsocket_create_server()
- *     allows as many protocols as you like to be handled by one server.
+ *     This structure represents one protocol supported by the server.  An
+ *     array of these structures is passed to libwebsocket_create_server()
+ *     allows as many protocols as you like to be handled by one server.
  */
 
 struct libwebsocket_protocols {
@@ -129,7 +129,7 @@ struct libwebsocket_protocols {
         * below are filled in on server init and can be left uninitialized,
         * no need for user to use them directly either
         */
-       
+
        struct libwebsocket_context *owning_server;
        int broadcast_socket_port;
        int broadcast_socket_user_fd;
@@ -142,6 +142,9 @@ libwebsocket_create_context(int port,
                  const char *ssl_cert_filepath,
                  const char *ssl_private_key_filepath, int gid, int uid);
 
+extern void
+libwebsocket_context_destroy(struct libwebsocket_context *this);
+
 extern int
 libwebsockets_fork_service_loop(struct libwebsocket_context *this);
 
@@ -188,7 +191,7 @@ libwebsockets_serve_http_file(struct libwebsocket *wsi, const char *file,
 /* notice - you need the pre- and post- padding allocation for buf below */
 
 extern int
-libwebsockets_broadcast(const struct libwebsocket_protocols * protocol,
+libwebsockets_broadcast(const struct libwebsocket_protocols *protocol,
                                                unsigned char *buf, size_t len);
 
 extern const struct libwebsocket_protocols *
index aafa38d..9d9efb3 100644 (file)
@@ -149,7 +149,7 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c)
                        debug("known hdr '%s'\n", wsi->name_buffer);
                        wsi->parser_state = WSI_TOKEN_GET_URI + n;
                        wsi->current_alloc_len = LWS_INITIAL_HDR_ALLOC;
-                       
+
                        wsi->utf8_token[wsi->parser_state].token =
                                                 malloc(wsi->current_alloc_len);
                        wsi->utf8_token[wsi->parser_state].token_len = 0;
@@ -220,7 +220,7 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c)
        return 0;
 }
 
-static unsigned char inline
+static inline unsigned char
 xor_mask(struct libwebsocket *wsi, unsigned char c)
 {
        c ^= wsi->masking_key_04[wsi->frame_mask_index++];
@@ -286,7 +286,7 @@ static int libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
                 * wsi->frame_mask_04 will be our recirculating 20-byte XOR key
                 * for this frame
                 */
-       
+
                SHA1((unsigned char *)buf, 4 + 20, wsi->frame_mask_04);
 
                /*
@@ -295,7 +295,7 @@ static int libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
                 */
 
                wsi->frame_mask_index = 0;
-               
+
                wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_1;
                break;
 
@@ -305,7 +305,7 @@ static int libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
         *
         * We ignore the possibility of extension data because we don't
         * negotiate any extensions at the moment.
-        * 
+        *
         *    0                   1                   2                   3
         *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
         *   +-+-+-+-+-------+-+-------------+-------------------------------+
@@ -334,23 +334,24 @@ static int libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
                 * 04 spec defines the opcode like this: (1, 2, and 3 are
                 * "control frame" opcodes which may not be fragmented or
                 * have size larger than 126)
-                * 
+                *
                 *       frame-opcode           =
-                *             %x0 ; continuation frame
-                *           / %x1 ; connection close
-                *           / %x2 ; ping
-                *           / %x3 ; pong
-                *           / %x4 ; text frame
-                *           / %x5 ; binary frame
-                *           / %x6-F ; reserved
+                *             %x0 ; continuation frame
+                *              / %x1 ; connection close
+                *              / %x2 ; ping
+                *              / %x3 ; pong
+                *              / %x4 ; text frame
+                *              / %x5 ; binary frame
+                *              / %x6-F ; reserved
                 *
-                *        FIN (b7)
+                *              FIN (b7)
                 */
 
                c = xor_mask(wsi, c);
 
                if (c & 0x70) {
-                       fprintf(stderr, "Frame has extensions set illegally 1\n");
+                       fprintf(stderr,
+                                     "Frame has extensions set illegally 1\n");
                        /* kill the connection */
                        return -1;
                }
@@ -412,7 +413,6 @@ static int libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
                        wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_8;
                        break;
                default:
-//                     fprintf(stderr, "seen incoming 04 frame len %d\n", c);
                        wsi->rx_packet_length = c;
                        wsi->lws_rx_parse_state =
                                        LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
@@ -605,51 +605,51 @@ int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c)
                        }
                        break;
                case 4:
-               /*
-                *  04 logical framing from the spec (all this is masked when incoming
-                *  and has to be unmasked)
-                *
-                * We ignore the possibility of extension data because we don't
-                * negotiate any extensions at the moment.
-                * 
-                *    0                   1                   2                   3
-                *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
-                *   +-+-+-+-+-------+-+-------------+-------------------------------+
-                *   |F|R|R|R| opcode|R| Payload len |    Extended payload length    |
-                *   |I|S|S|S|  (4)  |S|     (7)     |             (16/63)           |
-                *   |N|V|V|V|       |V|             |   (if payload len==126/127)   |
-                *   | |1|2|3|       |4|             |                               |
-                *   +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
-                *   |     Extended payload length continued, if payload len == 127  |
-                *   + - - - - - - - - - - - - - - - +-------------------------------+
-                *   |                               |         Extension data        |
-                *   +-------------------------------+ - - - - - - - - - - - - - - - +
-                *   :                                                               :
-                *   +---------------------------------------------------------------+
-                *   :                       Application data                        :
-                *   +---------------------------------------------------------------+
-                *
-                *  We pass payload through to userland as soon as we get it, ignoring
-                *  FIN.  It's up to userland to buffer it up if it wants to see a
-                *  whole unfragmented block of the original size (which may be up to
-                *  2^63 long!)
-                */
+       /*
+        *  04 logical framing from the spec (all this is masked when
+        *  incoming and has to be unmasked)
+        *
+        * We ignore the possibility of extension data because we don't
+        * negotiate any extensions at the moment.
+        *
+        *    0                   1                   2                   3
+        *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+        *   +-+-+-+-+-------+-+-------------+-------------------------------+
+        *   |F|R|R|R| opcode|R| Payload len |    Extended payload length    |
+        *   |I|S|S|S|  (4)  |S|     (7)     |             (16/63)           |
+        *   |N|V|V|V|       |V|             |   (if payload len==126/127)   |
+        *   | |1|2|3|       |4|             |                               |
+        *   +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
+        *   |     Extended payload length continued, if payload len == 127  |
+        *   + - - - - - - - - - - - - - - - +-------------------------------+
+        *   |                               |         Extension data        |
+        *   +-------------------------------+ - - - - - - - - - - - - - - - +
+        *   :                                                               :
+        *   +---------------------------------------------------------------+
+        *   :                       Application data                        :
+        *   +---------------------------------------------------------------+
+        *
+        *  We pass payload through to userland as soon as we get it, ignoring
+        *  FIN.  It's up to userland to buffer it up if it wants to see a
+        *  whole unfragmented block of the original size (which may be up to
+        *  2^63 long!)
+        */
 
                /*
                 * 04 spec defines the opcode like this: (1, 2, and 3 are
                 * "control frame" opcodes which may not be fragmented or
                 * have size larger than 126)
-                * 
+                *
                 *       frame-opcode           =
-                *             %x0 ; continuation frame
-                *           / %x1 ; connection close
-                *           / %x2 ; ping
-                *           / %x3 ; pong
-                *           / %x4 ; text frame
-                *           / %x5 ; binary frame
-                *           / %x6-F ; reserved
+                *                %x0 ; continuation frame
+                *              / %x1 ; connection close
+                *              / %x2 ; ping
+                *              / %x3 ; pong
+                *              / %x4 ; text frame
+                *              / %x5 ; binary frame
+                *              / %x6-F ; reserved
                 *
-                *        FIN (b7)
+                *              FIN (b7)
                 */
 
                        if (c & 0x70) {
@@ -1136,14 +1136,14 @@ send_raw:
        if (use_ssl) {
                n = SSL_write(wsi->ssl, buf - pre, len + pre + post);
                if (n < 0) {
-                       fprintf(stderr, "ERROR writing to socket");
+                       fprintf(stderr, "ERROR writing to socket\n");
                        return -1;
                }
        } else {
 #endif
-               n = send(wsi->sock, buf - pre, len + pre + post, 0);
+               n = send(wsi->sock, buf - pre, len + pre + post, MSG_NOSIGNAL);
                if (n < 0) {
-                       fprintf(stderr, "ERROR writing to socket");
+                       fprintf(stderr, "ERROR writing to socket\n");
                        return -1;
                }
 #ifdef LWS_OPENSSL_SUPPORT
@@ -1211,7 +1211,7 @@ int libwebsockets_serve_http_file(struct libwebsocket *wsi, const char *file,
 
 /**
  * libwebsockets_remaining_packet_payload() - Bytes to come before "overall"
- *                                           rx packet is complete
+ *                                           rx packet is complete
  * @wsi:               Websocket instance (available from user callback)
  *
  *     This function is intended to be called from the callback if the
index 6f35a1e..a263d83 100644 (file)
 #include <openssl/sha.h>
 #include "libwebsockets.h"
 
-//#define DEBUG 
-
+#if 0
+#define DEBUG
+#endif
 
 #ifdef DEBUG
-static inline void debug(const char *format, ...) {
+static inline void debug(const char *format, ...)
+{
        va_list ap;
        va_start(ap, format); vfprintf(stderr, format, ap); va_end(ap);
 }
 #else
-static inline void debug(const char *format, ...) { }
+static inline void debug(const char *format, ...)
+{
+}
 #endif
 
 #ifdef LWS_OPENSSL_SUPPORT
index 6def9b3..c8a3477 100644 (file)
@@ -1,3 +1,63 @@
+<h2>libwebsocket_context_destroy - Destroy the websocket context</h2>
+<i>void</i>
+<b>libwebsocket_context_destroy</b>
+(<i>struct libwebsocket_context *</i> <b>this</b>)
+<h3>Arguments</h3>
+<dl>
+<dt><b>this</b>
+<dd>Websocket context
+</dl>
+<h3>Description</h3>
+<blockquote>
+This function closes any active connections and then frees the
+context.  After calling this, any further use of the context is
+undefined.
+</blockquote>
+<hr>
+<h2>libwebsocket_service - Service any pending websocket activity</h2>
+<i>int</i>
+<b>libwebsocket_service</b>
+(<i>struct libwebsocket_context *</i> <b>this</b>,
+<i>int</i> <b>timeout_ms</b>)
+<h3>Arguments</h3>
+<dl>
+<dt><b>this</b>
+<dd>Websocket context
+<dt><b>timeout_ms</b>
+<dd>Timeout for poll; 0 means return immediately if nothing needed
+service otherwise block and service immediately, returning
+after the timeout if nothing needed service.
+</dl>
+<h3>Description</h3>
+<blockquote>
+This function deals with any pending websocket traffic, for three
+kinds of event.  It handles these events on both server and client
+types of connection the same.
+<p>
+1) Accept new connections to our context's server
+<p>
+2) Perform pending broadcast writes initiated from other forked
+processes (effectively serializing asynchronous broadcasts)
+<p>
+3) Call the receive callback for incoming frame data received by
+server or client connections.
+<p>
+You need to call this service function periodically to all the above
+functions to happen; if your application is single-threaded you can
+just call it in your main event loop.
+<p>
+Alternatively you can fork a new process that asynchronously handles
+calling this service in a loop.  In that case you are happy if this
+call blocks your thread until it needs to take care of something and
+would call it with a large nonzero timeout.  Your loop then takes no
+CPU while there is nothing happening.
+<p>
+If you are calling it in a single-threaded app, you don't want it to
+wait around blocking other things in your loop from happening, so you
+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_create_context - Create the websocket handler</h2>
 <i>struct libwebsocket_context *</i>
 <b>libwebsocket_create_context</b>
index 6869d6d..3243ccd 100644 (file)
@@ -380,6 +380,8 @@ int main(int argc, char **argv)
        libwebsocket_client_close(wsi_dumb);
        libwebsocket_client_close(wsi_mirror);
 
+       libwebsocket_context_destroy(context);
+
        return 0;
 
 usage:
index dc3cfd9..832a45a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * libwebsockets-test-server - libwebsockets test implementation
  *
- * Copyright (C) 2010 Andy Green <andy@warmcat.com>
+ * Copyright (C) 2010-2011 Andy Green <andy@warmcat.com>
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -233,7 +233,7 @@ int main(int argc, char **argv)
        struct libwebsocket_context *context;
 
        fprintf(stderr, "libwebsockets test server\n"
-                       "(C) Copyright 2010 Andy Green <andy@warmcat.com> "
+                       "(C) Copyright 2010-2011 Andy Green <andy@warmcat.com> "
                                                    "licensed under LGPL2.1\n");
 
        while (n >= 0) {
@@ -349,5 +349,7 @@ int main(int argc, char **argv)
 
 #endif
 
+       libwebsocket_context_destroy(context);
+
        return 0;
 }