introduce-new-05-socket-closure-rules.patch
authorAndy Green <andy.green@linaro.org>
Thu, 10 Feb 2011 09:07:05 +0000 (09:07 +0000)
committerAndy Green <andy.green@linaro.org>
Thu, 10 Feb 2011 09:07:05 +0000 (09:07 +0000)
Signed-off-by: Andy Green <andy.green@linaro.org>
lib/client-handshake.c
lib/libwebsockets.c
lib/libwebsockets.h
lib/parsers.c
lib/private-libwebsockets.h
test-server/test-client.c
test-server/test-ping.c

index 0624dcb..fa0f5a5 100644 (file)
@@ -20,10 +20,23 @@ libwebsocket_client_close(struct libwebsocket *wsi)
 {
        int n = wsi->state;
        struct libwebsocket_context *clients;
+       unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 2 +
+                                                 LWS_SEND_BUFFER_POST_PADDING];
 
        if (n == WSI_STATE_DEAD_SOCKET)
                return;
 
+       /*
+        * signal we are closing, libsocket_write will
+        * add any necessary version-specific stuff.  If the write fails,
+        * no worries we are closing anyway.  If we didn't initiate this
+        * close, then our state has been changed to
+        * WSI_STATE_RETURNED_CLOSE_ALREADY and we can skip this
+        */
+
+       if (n == WSI_STATE_ESTABLISHED)
+               libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], 0,
+                                                              LWS_WRITE_CLOSE);
        /* mark the WSI as dead and let the callback know */
 
        wsi->state = WSI_STATE_DEAD_SOCKET;
index d4c8ac4..afb0f07 100644 (file)
@@ -25,12 +25,29 @@ void
 libwebsocket_close_and_free_session(struct libwebsocket *wsi)
 {
        int n;
+       unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 2 +
+                                                 LWS_SEND_BUFFER_POST_PADDING];
 
        if ((unsigned long)wsi < LWS_MAX_PROTOCOLS)
                return;
 
        n = wsi->state;
 
+       if (n == WSI_STATE_DEAD_SOCKET)
+               return;
+
+       /*
+        * signal we are closing, libsocket_write will
+        * add any necessary version-specific stuff.  If the write fails,
+        * no worries we are closing anyway.  If we didn't initiate this
+        * close, then our state has been changed to
+        * WSI_STATE_RETURNED_CLOSE_ALREADY and we can skip this
+        */
+
+       if (n == WSI_STATE_ESTABLISHED)
+               libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], 0,
+                                                              LWS_WRITE_CLOSE);
+
        wsi->state = WSI_STATE_DEAD_SOCKET;
 
        if (wsi->protocol->callback && n == WSI_STATE_ESTABLISHED)
@@ -233,8 +250,10 @@ libwebsocket_context_destroy(struct libwebsocket_context *this)
                }
 
 #ifdef LWS_OPENSSL_SUPPORT
-       if (this->ssl_ctx)
+       if (this && this->ssl_ctx)
                SSL_CTX_free(this->ssl_ctx);
+       if (this && this->ssl_client_ctx)
+               SSL_CTX_free(this->ssl_client_ctx);
 #endif
 
        if (this)
@@ -300,7 +319,9 @@ libwebsocket_service(struct libwebsocket_context *this, int timeout_ms)
 
 
        if (n < 0 || this->fds[0].revents & (POLLERR | POLLHUP)) {
+               /*
                fprintf(stderr, "Listen Socket dead\n");
+               */
                goto fatal;
        }
        if (n == 0) /* poll timeout */
@@ -352,6 +373,7 @@ libwebsocket_service(struct libwebsocket_context *this, int timeout_ms)
 
 #ifdef LWS_OPENSSL_SUPPORT
                this->wsi[this->fds_count]->ssl = NULL;
+               this->ssl_ctx = NULL;
 
                if (this->use_ssl) {
 
@@ -451,22 +473,6 @@ 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);
-
-#ifdef LWS_OPENSSL_SUPPORT
-       if (this->ssl_ctx)
-               SSL_CTX_free(this->ssl_ctx);
-#endif
-
-       if (this)
-               free(this);
-
-       this = NULL;
-
        /* inform caller we are dead */
 
        return 1;
index 10d8584..0549a50 100644 (file)
@@ -46,7 +46,7 @@ enum libwebsocket_write_protocol {
        LWS_WRITE_BINARY,
        LWS_WRITE_HTTP,
 
-       /* special 04 opcodes */
+       /* special 04+ opcodes */
 
        LWS_WRITE_CLOSE,
        LWS_WRITE_PING,
index 45a64f4..a785438 100644 (file)
@@ -583,11 +583,12 @@ spill:
                        n = libwebsocket_write(wsi, (unsigned char *)
                           &wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
                                     wsi->rx_user_buffer_head, LWS_WRITE_CLOSE);
+                       wsi->state = WSI_STATE_RETURNED_CLOSE_ALREADY;
                        /* close the connection */
                        return -1;
 
                case LWS_WS_OPCODE_04__PING:
-                       /* parrot the ping packet payload back as a pong*/
+                       /* parrot the ping packet payload back as a pong */
                        n = libwebsocket_write(wsi, (unsigned char *)
                            &wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
                                    wsi->rx_user_buffer_head, LWS_WRITE_PONG);
@@ -902,6 +903,7 @@ spill:
                        n = libwebsocket_write(wsi, (unsigned char *)
                           &wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
                                     wsi->rx_user_buffer_head, LWS_WRITE_CLOSE);
+                       wsi->state = WSI_STATE_RETURNED_CLOSE_ALREADY;
                        /* close the connection */
                        return -1;
 
@@ -980,9 +982,9 @@ libwebsocket_0405_frame_mask_generate(struct libwebsocket *wsi)
        /* fetch the per-frame nonce */
 
        fd = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY);
-       if (fd < 1) {
-               fprintf(stderr, "Unable to open random device %s\n",
-                                                       SYSTEM_RANDOM_FILEPATH);
+       if (fd < 0) {
+               fprintf(stderr, "Unable to open random device %s %d\n",
+                                       SYSTEM_RANDOM_FILEPATH, fd);
                return 1;
        }
        n = read(fd, wsi->frame_masking_nonce_04, 4);
@@ -1051,7 +1053,7 @@ int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
        int post = 0;
        unsigned int shift = 7;
 
-       if (len == 0) {
+       if (len == 0 && protocol != LWS_WRITE_CLOSE) {
                fprintf(stderr, "zero length libwebsocket_write attempt\n");
                return 0;
        }
@@ -1109,6 +1111,34 @@ int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
                        break;
                case LWS_WRITE_CLOSE:
                        n = LWS_WS_OPCODE_04__CLOSE;
+
+                       /*
+                        * v5 mandates the first byte of close packet
+                        * in both client and server directions
+                        */
+                       
+                       if (wsi->ietf_spec_revision >= 5) {
+
+                               /* we can do this because we demand post-buf */
+
+                               if (len < 1)
+                                       len = 1;
+                               
+                               switch (wsi->mode) {
+                               case LWS_CONNMODE_WS_SERVING:
+                                       /*
+                                       fprintf(stderr, "LWS_WRITE_CLOSE S\n");
+                                       */
+                                       buf[0] = 'S';
+                                       break;
+                               case LWS_CONNMODE_WS_CLIENT:
+                                       /*
+                                       fprintf(stderr, "LWS_WRITE_CLOSE C\n");
+                                       */
+                                       buf[0] = 'C';
+                                       break;
+                               }
+                       }
                        break;
                case LWS_WRITE_PING:
                        n = LWS_WS_OPCODE_04__PING;
index 5c8de5d..71241e7 100644 (file)
@@ -95,7 +95,8 @@ enum lws_connection_states {
        WSI_STATE_HTTP_HEADERS,
        WSI_STATE_DEAD_SOCKET,
        WSI_STATE_ESTABLISHED,
-       WSI_STATE_CLIENT_UNCONNECTED
+       WSI_STATE_CLIENT_UNCONNECTED,
+       WSI_STATE_RETURNED_CLOSE_ALREADY
 };
 
 enum lws_token_indexes {
index 3508a52..298d013 100644 (file)
@@ -264,6 +264,6 @@ int main(int argc, char **argv)
 usage:
        fprintf(stderr, "Usage: libwebsockets-test-client "
                                             "<server address> [--port=<p>] "
-                                            "[--ssl]\n");
+                                            "[--ssl] [-k] [-v <ver>]\n");
        return 1;
 }
index 25a3226..0022ac5 100644 (file)
@@ -514,6 +514,7 @@ usage:
                                             "[--protocol=<protocolname>] "
                                             "[--mirror] "
                                             "[--replicate=clients>]"
+                                            "[--version <version>]"
                                             "\n");
        return 1;
 }