require close reason argument on close and free session
authorAndy Green <andy@warmcat.com>
Sat, 26 Feb 2011 11:04:01 +0000 (11:04 +0000)
committerAndy Green <andy@warmcat.com>
Sat, 26 Feb 2011 11:04:01 +0000 (11:04 +0000)
Signed-off-by: Andy Green <andy@warmcat.com>
lib/handshake.c
lib/libwebsockets.c
lib/libwebsockets.h
lib/parsers.c
lib/private-libwebsockets.h

index 91214b8..b4779f4 100644 (file)
@@ -611,7 +611,8 @@ libwebsocket_read(struct libwebsocket_context *this, struct libwebsocket *wsi,
        return 0;
 
 bail:
-       libwebsocket_close_and_free_session(this, wsi);
+       libwebsocket_close_and_free_session(this, wsi,
+                                                    LWS_CLOSE_STATUS_NOSTATUS);
 
        return -1;
 }
index 397dc70..12c8778 100644 (file)
@@ -131,7 +131,7 @@ interface_to_sa(const char* ifname, struct sockaddr_in *addr, size_t addrlen)
 
 void
 libwebsocket_close_and_free_session(struct libwebsocket_context *this,
-                                                      struct libwebsocket *wsi)
+                        struct libwebsocket *wsi, enum lws_close_status reason)
 {
        int n;
        int old_state;
@@ -169,6 +169,8 @@ libwebsocket_close_and_free_session(struct libwebsocket_context *this,
        this->protocols[0].callback(this, wsi,
                    LWS_CALLBACK_DEL_POLL_FD, (void *)(long)wsi->sock, NULL, 0);
 
+       wsi->close_reason = reason;
+
        /*
         * signal we are closing, libsocket_write will
         * add any necessary version-specific stuff.  If the write fails,
@@ -244,7 +246,7 @@ libwebsockets_hangup_on_client(struct libwebsocket_context *this, int fd)
                        this->fds_count--;
                }
 
-       libwebsocket_close_and_free_session(this, wsi);
+       libwebsocket_close_and_free_session(this, wsi, 0);
 }
 
 
@@ -375,7 +377,8 @@ libwebsocket_service_fd(struct libwebsocket_context *this,
                         */
 
                        if (tv.tv_sec > wsi->pending_timeout_limit)
-                               libwebsocket_close_and_free_session(this, wsi);
+                               libwebsocket_close_and_free_session(this, wsi,
+                                                    LWS_CLOSE_STATUS_NOSTATUS);
                }
        }
 
@@ -590,7 +593,8 @@ libwebsocket_service_fd(struct libwebsocket_context *this,
                        debug("Session Socket %p (fd=%d) dead\n",
                                (void *)wsi, pollfd->fd);
 
-                       libwebsocket_close_and_free_session(this, wsi);
+                       libwebsocket_close_and_free_session(this, wsi,
+                                                      LWS_CLOSE_STATUS_NORMAL);
                        return 1;
                }
 
@@ -676,20 +680,23 @@ libwebsocket_service_fd(struct libwebsocket_context *this,
                        fprintf(stderr, "Proxy connection %p (fd=%d) dead\n",
                                (void *)wsi, pollfd->fd);
 
-                       libwebsocket_close_and_free_session(this, wsi);
+                       libwebsocket_close_and_free_session(this, wsi,
+                                                    LWS_CLOSE_STATUS_NOSTATUS);
                        return 1;
                }
 
                n = recv(wsi->sock, pkt, sizeof pkt, 0);
                if (n < 0) {
-                       libwebsocket_close_and_free_session(this, wsi);
+                       libwebsocket_close_and_free_session(this, wsi,
+                                                    LWS_CLOSE_STATUS_NOSTATUS);
                        fprintf(stderr, "ERROR reading from proxy socket\n");
                        return 1;
                }
 
                pkt[13] = '\0';
                if (strcmp(pkt, "HTTP/1.0 200 ") != 0) {
-                       libwebsocket_close_and_free_session(this, wsi);
+                       libwebsocket_close_and_free_session(this, wsi,
+                                                    LWS_CLOSE_STATUS_NOSTATUS);
                        fprintf(stderr, "ERROR from proxy: %s\n", pkt);
                        return 1;
                }
@@ -714,21 +721,23 @@ libwebsocket_service_fd(struct libwebsocket_context *this,
 
                        if (SSL_connect(wsi->ssl) <= 0) {
                                fprintf(stderr, "SSL connect error %s\n",
-                                       ERR_error_string(ERR_get_error(), ssl_err_buf));
-                               libwebsocket_close_and_free_session(this, wsi);
+                                       ERR_error_string(ERR_get_error(),
+                                                                 ssl_err_buf));
+                               libwebsocket_close_and_free_session(this, wsi,
+                                                    LWS_CLOSE_STATUS_NOSTATUS);
                                return 1;
                        }
 
                        n = SSL_get_verify_result(wsi->ssl);
-                       if (n != X509_V_OK) {
-                               if (n != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
-                                                           wsi->use_ssl != 2) {
-
-                                       fprintf(stderr, "server's cert didn't "
-                                                                  "look good %d\n", n);
-                                       libwebsocket_close_and_free_session(this, wsi);
-                                       return 1;
-                               }
+                       if (n != X509_V_OK) && (
+                               n != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
+                                                          wsi->use_ssl != 2)) {
+
+                               fprintf(stderr, "server's cert didn't "
+                                                          "look good %d\n", n);
+                               libwebsocket_close_and_free_session(this, wsi,
+                                                    LWS_CLOSE_STATUS_NOSTATUS);
+                               return 1;
                        }
                } else {
                        wsi->ssl = NULL;
@@ -753,7 +762,8 @@ libwebsocket_service_fd(struct libwebsocket_context *this,
                                free(wsi->c_origin);
                        if (wsi->c_protocol)
                                free(wsi->c_protocol);
-                       libwebsocket_close_and_free_session(this, wsi);
+                       libwebsocket_close_and_free_session(this, wsi,
+                                                    LWS_CLOSE_STATUS_NOSTATUS);
                        return 1;
                }
 
@@ -819,7 +829,8 @@ libwebsocket_service_fd(struct libwebsocket_context *this,
 
                if (n < 0) {
                        fprintf(stderr, "ERROR writing to client socket\n");
-                       libwebsocket_close_and_free_session(this, wsi);
+                       libwebsocket_close_and_free_session(this, wsi,
+                                                    LWS_CLOSE_STATUS_NOSTATUS);
                        return 1;
                }
 
@@ -890,7 +901,7 @@ libwebsocket_service_fd(struct libwebsocket_context *this,
                        (!wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len &&
                                                     wsi->c_protocol != NULL)) {
                        fprintf(stderr, "libwebsocket_client_handshake "
-                                                       "missing required header(s)\n");
+                                               "missing required header(s)\n");
                        pkt[len] = '\0';
                        fprintf(stderr, "%s", pkt);
                        goto bail3;
@@ -1061,7 +1072,8 @@ bail3:
                        free(wsi->c_protocol);
 
 bail2:
-               libwebsocket_close_and_free_session(this, wsi);
+               libwebsocket_close_and_free_session(this, wsi,
+                                                    LWS_CLOSE_STATUS_NOSTATUS);
                return 1;
                
 
@@ -1075,7 +1087,8 @@ bail2:
                        fprintf(stderr, "Session Socket %p (fd=%d) dead\n",
                                (void *)wsi, pollfd->fd);
 
-                       libwebsocket_close_and_free_session(this, wsi);
+                       libwebsocket_close_and_free_session(this, wsi,
+                                                    LWS_CLOSE_STATUS_NOSTATUS);
                        return 1;
                }
 
@@ -1113,7 +1126,8 @@ bail2:
                        break;
                }
                if (!n) {
-                       libwebsocket_close_and_free_session(this, wsi);
+                       libwebsocket_close_and_free_session(this, wsi,
+                                                    LWS_CLOSE_STATUS_NOSTATUS);
                        return 1;
                }
 
@@ -1150,7 +1164,8 @@ libwebsocket_context_destroy(struct libwebsocket_context *this)
        for (n = 0; n < FD_HASHTABLE_MODULUS; n++)
                for (m = 0; m < this->fd_hashtable[n].length; m++) {
                        wsi = this->fd_hashtable[n].wsi[m];
-                       libwebsocket_close_and_free_session(this, wsi);
+                       libwebsocket_close_and_free_session(this, wsi,
+                                                   LWS_CLOSE_STATUS_GOINGAWAY);
                }
 
        close(this->fd_random);
index 620c576..fe7238f 100644 (file)
@@ -123,6 +123,45 @@ enum lws_token_indexes {
        WSI_PARSING_COMPLETE
 };
 
+/*
+ * From 06 sped
+   1000
+
+      1000 indicates a normal closure, meaning whatever purpose the
+      connection was established for has been fulfilled.
+
+   1001
+
+      1001 indicates that an endpoint is "going away", such as a server
+      going down, or a browser having navigated away from a page.
+
+   1002
+
+      1002 indicates that an endpoint is terminating the connection due
+      to a protocol error.
+
+   1003
+
+      1003 indicates that an endpoint is terminating the connection
+      because it has received a type of data it cannot accept (e.g. an
+      endpoint that understands only text data may send this if it
+      receives a binary message.)
+
+   1004
+
+      1004 indicates that an endpoint is terminating the connection
+      because it has received a message that is too large.
+*/
+
+enum lws_close_status {
+       LWS_CLOSE_STATUS_NOSTATUS = 0,
+       LWS_CLOSE_STATUS_NORMAL = 1000,
+       LWS_CLOSE_STATUS_GOINGAWAY = 1001,
+       LWS_CLOSE_STATUS_PROTOCOL_ERR = 1002,
+       LWS_CLOSE_STATUS_UNACCEPTABLE_OPCODE = 1003,
+       LWS_CLOSE_STATUS_PAYLOAD_TOO_LARGE = 1004,
+};
+
 struct libwebsocket;
 struct libwebsocket_context;
 
@@ -367,7 +406,11 @@ libwebsocket_service_fd(struct libwebsocket_context *context,
  * use the whole buffer without taking care of the above.
  */
 
-/* this is the frame nonce plus two header plus 8 length */
+/*
+ * this is the frame nonce plus two header plus 8 length
+ * 2 byte prepend on close will already fit because control frames cannot use
+ * the big length style
+ */
 
 #define LWS_SEND_BUFFER_PRE_PADDING (4 + 10)
 #define LWS_SEND_BUFFER_POST_PADDING 1
@@ -430,6 +473,6 @@ libwebsockets_hangup_on_client(struct libwebsocket_context *context, int fd);
 
 extern void
 libwebsocket_close_and_free_session(struct libwebsocket_context *context,
-                                                     struct libwebsocket *wsi);
+                              struct libwebsocket *wsi, enum lws_close_status);
 
 #endif
index d6cae1c..481caf1 100644 (file)
@@ -1139,8 +1139,11 @@ int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
                         * in both client and server directions
                         */
                        
-                       if (wsi->ietf_spec_revision >= 5) {
-
+                       switch (wsi->ietf_spec_revision) {
+                       case 0:
+                       case 4:
+                               break;
+                       case 5:
                                /* we can do this because we demand post-buf */
 
                                if (len < 1)
@@ -1162,6 +1165,19 @@ int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
                                default:
                                        break;
                                }
+                               break;
+                       default:
+                               /*
+                                * 06 has a 2-byte status code in network order
+                                * we can do this because we demand post-buf
+                                */
+
+                               if (wsi->close_reason) {
+                                       buf[pre - 2] = wsi->close_reason >> 8;
+                                       buf[pre - 1] = wsi->close_reason;
+                                       pre += 2;
+                               }
+                               break;
                        }
                        break;
                case LWS_WRITE_PING:
@@ -1181,35 +1197,35 @@ int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
                        n |= 1 << 7;
 
                if (len < 126) {
-                       buf[-2] = n;
-                       buf[-1] = len;
-                       pre = 2;
+                       buf[pre - 2] = n;
+                       buf[pre - 1] = len;
+                       pre += 2;
                } else {
                        if (len < 65536) {
-                               buf[-4] = n;
-                               buf[-3] = 126;
-                               buf[-2] = len >> 8;
-                               buf[-1] = len;
-                               pre = 4;
+                               buf[pre - 4] = n;
+                               buf[pre - 3] = 126;
+                               buf[pre - 2] = len >> 8;
+                               buf[pre - 1] = len;
+                               pre += 4;
                        } else {
-                               buf[-10] = n;
-                               buf[-9] = 127;
+                               buf[pre - 10] = n;
+                               buf[pre - 9] = 127;
 #if defined __LP64__
-                                       buf[-8] = (len >> 56) & 0x7f;
-                                       buf[-7] = len >> 48;
-                                       buf[-6] = len >> 40;
-                                       buf[-5] = len >> 32;
+                                       buf[pre - 8] = (len >> 56) & 0x7f;
+                                       buf[pre - 7] = len >> 48;
+                                       buf[pre - 6] = len >> 40;
+                                       buf[pre - 5] = len >> 32;
 #else
-                                       buf[-8] = 0;
-                                       buf[-7] = 0;
-                                       buf[-6] = 0;
-                                       buf[-5] = 0;
+                                       buf[pre - 8] = 0;
+                                       buf[pre - 7] = 0;
+                                       buf[pre - 6] = 0;
+                                       buf[pre - 5] = 0;
 #endif
-                               buf[-4] = len >> 24;
-                               buf[-3] = len >> 16;
-                               buf[-2] = len >> 8;
-                               buf[-1] = len;
-                               pre = 10;
+                               buf[pre - 4] = len >> 24;
+                               buf[pre - 3] = len >> 16;
+                               buf[pre - 2] = len >> 8;
+                               buf[pre - 1] = len;
+                               pre += 10;
                        }
                }
                break;
index 9d3723e..493fd22 100644 (file)
@@ -93,44 +93,6 @@ static inline void debug(const char *format, ...)
 #define MAX_WEBSOCKET_04_KEY_LEN 128
 #define SYSTEM_RANDOM_FILEPATH "/dev/urandom"
 
-/*
- * From 06 sped
-   1000
-
-      1000 indicates a normal closure, meaning whatever purpose the
-      connection was established for has been fulfilled.
-
-   1001
-
-      1001 indicates that an endpoint is "going away", such as a server
-      going down, or a browser having navigated away from a page.
-
-   1002
-
-      1002 indicates that an endpoint is terminating the connection due
-      to a protocol error.
-
-   1003
-
-      1003 indicates that an endpoint is terminating the connection
-      because it has received a type of data it cannot accept (e.g. an
-      endpoint that understands only text data may send this if it
-      receives a binary message.)
-
-   1004
-
-      1004 indicates that an endpoint is terminating the connection
-      because it has received a message that is too large.
-*/
-
-enum lws_close_status {
-       LWS_CLOSE_STATUS_NORMAL = 1000,
-       LWS_CLOSE_STATUS_GOINGAWAY = 1001,
-       LWS_CLOSE_STATUS_PROTOCOL_ERR = 1002,
-       LWS_CLOSE_STATUS_UNACCEPTABLE_OPCODE = 1003,
-       LWS_CLOSE_STATUS_PAYLOAD_TOO_LARGE = 1004,
-};
-
 enum lws_websocket_opcodes_04 {
        LWS_WS_OPCODE_04__CONTINUATION = 0,
        LWS_WS_OPCODE_04__CLOSE = 1,
@@ -278,6 +240,8 @@ struct libwebsocket {
        unsigned char (*xor_mask)(struct libwebsocket *, unsigned char);
        char all_zero_nonce;
 
+       enum lws_close_status close_reason;
+
        /* client support */
        char initial_handshake_hash_base64[30];
        enum connection_mode mode;