introduce-ietf-05-framing-and-commandline-options.patch
authorAndy Green <andy@warmcat.com>
Wed, 9 Feb 2011 08:49:14 +0000 (08:49 +0000)
committerAndy Green <andy@linaro.org>
Wed, 9 Feb 2011 08:49:14 +0000 (08:49 +0000)
This adds 05 support, and -v switches on test-client and test-ping
to allow setting their ietf protocol version to 4 or 5.

It also optimizes the masking to us a function pointer, which
takes some conditionals out of the fast path.

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-ping.c

index b805cd1..0624dcb 100644 (file)
@@ -87,6 +87,8 @@ libwebsocket_client_close(struct libwebsocket *wsi)
  * @protocol:  Comma-separated list of protocols being asked for from
  *             the server, or just one.  The server will pick the one it
  *             likes best.
+ * @ietf_version_or_minus_one: -1 to ask to connect using the default, latest
+ *             protocol supported, or the specific protocol ordinal
  *
  *     This function creates a connection to a remote server
  */
@@ -99,7 +101,8 @@ libwebsocket_client_connect(struct libwebsocket_context *this,
                              const char *path,
                              const char *host,
                              const char *origin,
-                             const char *protocol)
+                             const char *protocol,
+                             int ietf_version_or_minus_one)
 {
        struct hostent *server_hostent;
        struct sockaddr_in server_addr;
@@ -137,13 +140,41 @@ libwebsocket_client_connect(struct libwebsocket_context *this,
 
        this->wsi[this->fds_count] = wsi;
 
-       wsi->ietf_spec_revision = 4;
+       /* -1 means just use latest supported */
+
+       if (ietf_version_or_minus_one == -1)
+               ietf_version_or_minus_one = 5;
+
+       wsi->ietf_spec_revision = ietf_version_or_minus_one;
        wsi->name_buffer_pos = 0;
        wsi->user_space = NULL;
        wsi->state = WSI_STATE_CLIENT_UNCONNECTED;
        wsi->pings_vs_pongs = 0;
        wsi->protocol = NULL;
 
+       /* set up appropriate masking */
+
+       wsi->xor_mask = xor_no_mask;
+
+       switch (wsi->ietf_spec_revision) {
+       case 4:
+               wsi->xor_mask = xor_mask_04;
+               break;
+       case 5:
+               wsi->xor_mask = xor_mask_05;
+               break;
+       default:
+               fprintf(stderr,
+                       "Client ietf version %d not supported\n",
+                                                      wsi->ietf_spec_revision);
+               return NULL;
+       }
+
+       /* force no mask if he asks for that though */
+
+       if (this->options & LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK)
+               wsi->xor_mask = xor_no_mask;
+
        for (n = 0; n < WSI_TOKEN_COUNT; n++) {
                wsi->utf8_token[n].token = NULL;
                wsi->utf8_token[n].token_len = 0;
@@ -309,7 +340,8 @@ libwebsocket_client_connect(struct libwebsocket_context *this,
         p += sprintf(p, "\x0d\x0aSec-WebSocket-Origin: %s\x0d\x0a", origin);
         if (protocol != NULL)
                p += sprintf(p, "Sec-WebSocket-Protocol: %s\x0d\x0a", protocol);
-        p += sprintf(p, "Sec-WebSocket-Version: 4\x0d\x0a\x0d\x0a");
+        p += sprintf(p, "Sec-WebSocket-Version: %d\x0d\x0a\x0d\x0a",
+                                                      wsi->ietf_spec_revision);
 
 
        /* prepare the expected server accept response */
index ab2f09e..2a4ebb6 100644 (file)
@@ -222,7 +222,7 @@ bail:
  */
 
 static int
-handshake_04(struct libwebsocket *wsi)
+handshake_0405(struct libwebsocket *wsi)
 {
        static const char *websocket_magic_guid_04 =
                                         "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
@@ -537,7 +537,6 @@ libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len)
                        wsi->ietf_spec_revision =
                                 atoi(wsi->utf8_token[WSI_TOKEN_VERSION].token);
 
-
                /*
                 * Perform the handshake according to the protocol version the
                 * client announced
@@ -545,20 +544,32 @@ libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len)
 
                switch (wsi->ietf_spec_revision) {
                case 0: /* applies to 76 and 00 */
+                       wsi->xor_mask = xor_no_mask;
                        if (handshake_00(wsi))
                                goto bail;
                        break;
                case 4: /* 04 */
+                       wsi->xor_mask = xor_mask_04;
+                       debug("libwebsocket_parse calling handshake_04\n");
+                       if (handshake_0405(wsi))
+                               goto bail;
+                       break;
+               case 5: /* 05 */
+                       wsi->xor_mask = xor_mask_05;
                        debug("libwebsocket_parse calling handshake_04\n");
-                       if (handshake_04(wsi))
+                       if (handshake_0405(wsi))
                                goto bail;
                        break;
+
                default:
                        fprintf(stderr, "Unknown client spec version %d\n",
                                                       wsi->ietf_spec_revision);
                        goto bail;
                }
 
+               fprintf(stderr, "accepted v%02d connection\n",
+                                                      wsi->ietf_spec_revision);
+
                break;
 
        case WSI_STATE_ESTABLISHED:
index 6a74a77..d4c8ac4 100644 (file)
@@ -607,6 +607,7 @@ static void sigpipe_handler(int x)
  *                     else ignored
  * @gid:       group id to change to after setting listen socket, or -1.
  * @uid:       user id to change to after setting listen socket, or -1.
+ * @options:   0, or LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK
  *
  *     This function creates the listening socket and takes care
  *     of all initialization in one step.
index e579303..10d8584 100644 (file)
 
 #define CONTEXT_PORT_NO_LISTEN 0
 
-#define LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK 1
+
+enum libwebsocket_context_options {
+       LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK = 1,
+};
 
 enum libwebsocket_callback_reasons {
        LWS_CALLBACK_ESTABLISHED,
@@ -258,7 +261,8 @@ libwebsocket_client_connect(struct libwebsocket_context *clients,
                              const char *path,
                              const char *host,
                              const char *origin,
-                             const char *protocol);
+                             const char *protocol,
+                             int ietf_version_or_minus_one);
 
 extern const char *
 libwebsocket_canonical_hostname(struct libwebsocket_context *this);
index 304c574..7551f14 100644 (file)
@@ -220,13 +220,15 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c)
        return 0;
 }
 
-static inline unsigned char
-xor_mask(struct libwebsocket *wsi, unsigned char c)
+unsigned char
+xor_no_mask(struct libwebsocket *wsi, unsigned char c)
+{
+       return c;
+}
+
+unsigned char
+xor_mask_04(struct libwebsocket *wsi, unsigned char c)
 {
-       if (wsi->protocol->owning_server->options &
-                                          LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK)
-               return c;
-       
        c ^= wsi->masking_key_04[wsi->frame_mask_index++];
        if (wsi->frame_mask_index == 20)
                wsi->frame_mask_index = 0;
@@ -234,6 +236,13 @@ xor_mask(struct libwebsocket *wsi, unsigned char c)
        return c;
 }
 
+unsigned char
+xor_mask_05(struct libwebsocket *wsi, unsigned char c)
+{
+       return c ^ wsi->frame_masking_nonce_04[(wsi->frame_mask_index++) & 3];
+}
+
+
 
 static int libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
 {
@@ -255,9 +264,14 @@ static int libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
                        }
                        break;
                case 4:
+               case 5:
                        wsi->frame_masking_nonce_04[0] = c;
                        wsi->lws_rx_parse_state = LWS_RXPS_04_MASK_NONCE_1;
                        break;
+               default:
+                       fprintf(stderr, "libwebsocket_rx_sm doesn't know "
+                           "about spec version %d\n", wsi->ietf_spec_revision);
+                       break;
                }
                break;
        case LWS_RXPS_04_MASK_NONCE_1:
@@ -275,6 +289,9 @@ static int libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
                                           LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK)
                        goto post_mask;
 
+               if (wsi->ietf_spec_revision > 4)
+                       goto post_sha1;
+
                /*
                 * we are able to compute the frame key now
                 * it's a SHA1 of ( frame nonce we were just sent, concatenated
@@ -297,6 +314,8 @@ static int libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
 
                SHA1((unsigned char *)buf, 4 + 20, wsi->frame_mask_04);
 
+post_sha1:
+
                /*
                 * start from the zero'th byte in the XOR key buffer since
                 * this is the start of a frame with a new key
@@ -356,7 +375,7 @@ post_mask:
                 *              FIN (b7)
                 */
 
-               c = xor_mask(wsi, c);
+               c = wsi->xor_mask(wsi, c);
 
                if (c & 0x70) {
                        fprintf(stderr,
@@ -381,7 +400,7 @@ post_mask:
                break;
 
        case LWS_RXPS_04_FRAME_HDR_LEN:
-               c = xor_mask(wsi, c);
+               c = wsi->xor_mask(wsi, c);
 
                if (c & 0x80) {
                        fprintf(stderr, "Frame has extensions "
@@ -430,14 +449,14 @@ post_mask:
                break;
 
        case LWS_RXPS_04_FRAME_HDR_LEN16_2:
-               c = xor_mask(wsi, c);
+               c = wsi->xor_mask(wsi, c);
 
                wsi->rx_packet_length = c << 8;
                wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_1;
                break;
 
        case LWS_RXPS_04_FRAME_HDR_LEN16_1:
-               c = xor_mask(wsi, c);
+               c = wsi->xor_mask(wsi, c);
 
                wsi->rx_packet_length |= c;
                wsi->lws_rx_parse_state =
@@ -445,7 +464,7 @@ post_mask:
                break;
 
        case LWS_RXPS_04_FRAME_HDR_LEN64_8:
-               c = xor_mask(wsi, c);
+               c = wsi->xor_mask(wsi, c);
                if (c & 0x80) {
                        fprintf(stderr, "b63 of length must be zero\n");
                        /* kill the connection */
@@ -461,42 +480,42 @@ post_mask:
 
        case LWS_RXPS_04_FRAME_HDR_LEN64_7:
 #if defined __LP64__
-               wsi->rx_packet_length |= ((size_t)xor_mask(wsi, c)) << 48;
+               wsi->rx_packet_length |= ((size_t)wsi->xor_mask(wsi, c)) << 48;
 #endif
                wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_6;
                break;
 
        case LWS_RXPS_04_FRAME_HDR_LEN64_6:
 #if defined __LP64__
-               wsi->rx_packet_length |= ((size_t)xor_mask(wsi, c)) << 40;
+               wsi->rx_packet_length |= ((size_t)wsi->xor_mask(wsi, c)) << 40;
 #endif
                wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_5;
                break;
 
        case LWS_RXPS_04_FRAME_HDR_LEN64_5:
 #if defined __LP64__
-               wsi->rx_packet_length |= ((size_t)xor_mask(wsi, c)) << 32;
+               wsi->rx_packet_length |= ((size_t)wsi->xor_mask(wsi, c)) << 32;
 #endif
                wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_4;
                break;
 
        case LWS_RXPS_04_FRAME_HDR_LEN64_4:
-               wsi->rx_packet_length |= ((size_t)xor_mask(wsi, c)) << 24;
+               wsi->rx_packet_length |= ((size_t)wsi->xor_mask(wsi, c)) << 24;
                wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_3;
                break;
 
        case LWS_RXPS_04_FRAME_HDR_LEN64_3:
-               wsi->rx_packet_length |= ((size_t)xor_mask(wsi, c)) << 16;
+               wsi->rx_packet_length |= ((size_t)wsi->xor_mask(wsi, c)) << 16;
                wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_2;
                break;
 
        case LWS_RXPS_04_FRAME_HDR_LEN64_2:
-               wsi->rx_packet_length |= ((size_t)xor_mask(wsi, c)) << 8;
+               wsi->rx_packet_length |= ((size_t)wsi->xor_mask(wsi, c)) << 8;
                wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_1;
                break;
 
        case LWS_RXPS_04_FRAME_HDR_LEN64_1:
-               wsi->rx_packet_length |= ((size_t)xor_mask(wsi, c));
+               wsi->rx_packet_length |= ((size_t)wsi->xor_mask(wsi, c));
                wsi->lws_rx_parse_state =
                                        LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
                break;
@@ -541,7 +560,8 @@ issue:
 
        case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED:
                wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
-                              (wsi->rx_user_buffer_head++)] = xor_mask(wsi, c);
+                              (wsi->rx_user_buffer_head++)] =
+                                                         wsi->xor_mask(wsi, c);
 
                if (--wsi->rx_packet_length == 0) {
                        wsi->lws_rx_parse_state = LWS_RXPS_NEW;
@@ -627,6 +647,7 @@ int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c)
                        }
                        break;
                case 4:
+               case 5:
        /*
         *  04 logical framing from the spec (all this is masked when
         *  incoming and has to be unmasked)
@@ -695,6 +716,11 @@ int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c)
 
                        wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN;
                        break;
+               default:
+                       fprintf(stderr, "client_rx_sm doesn't know how "
+                               "to handle spec version %02d\n",
+                                                      wsi->ietf_spec_revision);
+                       break;
                }
                break;
 
@@ -943,7 +969,7 @@ int libwebsocket_interpret_incoming_packet(struct libwebsocket *wsi,
 
 
 static int
-libwebsocket_04_frame_mask_generate(struct libwebsocket *wsi)
+libwebsocket_0405_frame_mask_generate(struct libwebsocket *wsi)
 {
        int fd;
        char buf[4 + 20];
@@ -965,21 +991,27 @@ libwebsocket_04_frame_mask_generate(struct libwebsocket *wsi)
        }
        close(fd);
 
+       /* start masking from first byte of masking key buffer */
+       wsi->frame_mask_index = 0;
+
+       if (wsi->ietf_spec_revision != 4)
+               return 0;
+
+       /* 04 only does SHA-1 more complex key */
+
        /*
         * the frame key is the frame nonce (4 bytes) followed by the
         * connection masking key, hashed by SHA1
         */
 
        memcpy(buf, wsi->frame_masking_nonce_04, 4);
+       
        memcpy(buf + 4, wsi->masking_key_04, 20);
 
        /* concatenate the nonce with the connection key then hash it */
 
        SHA1((unsigned char *)buf, 4 + 20, wsi->frame_mask_04);
 
-       /* start masking from first byte of masking key buffer */
-       wsi->frame_mask_index = 0;
-
        return 0;
 }
 
@@ -1065,7 +1097,7 @@ int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
                break;
 
        case 4:
-
+       case 5:
                switch (protocol & 0xf) {
                case LWS_WRITE_TEXT:
                        n = LWS_WS_OPCODE_04__TEXT_FRAME;
@@ -1135,11 +1167,12 @@ int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
 #endif
 
        /*
-        * Deal with masking if appropriate
+        * Deal with masking if we are in client -> server direction and
+        * the protocol demands it
         */
 
        if (wsi->mode == LWS_CONNMODE_WS_CLIENT &&
-                                                wsi->ietf_spec_revision == 4) {
+                                                wsi->ietf_spec_revision >= 4) {
 
                /*
                 * this is only useful for security tests where it's required
@@ -1148,7 +1181,7 @@ int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
 
                if (!(protocol & LWS_WRITE_CLIENT_IGNORE_XOR_MASK)) {
 
-                       if (libwebsocket_04_frame_mask_generate(wsi)) {
+                       if (libwebsocket_0405_frame_mask_generate(wsi)) {
                                fprintf(stderr, "libwebsocket_write: "
                                              "frame mask generation failed\n");
                                return 1;
@@ -1160,7 +1193,7 @@ int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
                         */
 
                        for (n = 0; n < (len + pre + post); n++)
-                               buf[n - pre] = xor_mask(wsi, buf[n - pre]);
+                               buf[n - pre] = wsi->xor_mask(wsi, buf[n - pre]);
                }
 
                /* make space for the frame nonce in clear */
@@ -1168,6 +1201,7 @@ int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
 
                /* copy the frame nonce into place */
                memcpy(&buf[0 - pre], wsi->frame_masking_nonce_04, 4);
+
        }
 
 send_raw:
index 8028b94..14d4fb5 100644 (file)
@@ -224,6 +224,7 @@ struct libwebsocket {
        unsigned char final;
 
        int pings_vs_pongs;
+       unsigned char (*xor_mask)(struct libwebsocket *, unsigned char);
 
        /* client support */
        char initial_handshake_hash_base64[30];
@@ -261,3 +262,12 @@ lws_b64_decode_string(const char *in, char *out, int out_size);
 
 extern int
 lws_b64_selftest(void);
+
+extern unsigned char
+xor_no_mask(struct libwebsocket *wsi, unsigned char c);
+
+extern unsigned char
+xor_mask_04(struct libwebsocket *wsi, unsigned char c);
+
+extern unsigned char
+xor_mask_05(struct libwebsocket *wsi, unsigned char c);
index b98904f..422ed7c 100644 (file)
@@ -161,6 +161,8 @@ else ignored
 <dd>group id to change to after setting listen socket, or -1.
 <dt><b>uid</b>
 <dd>user id to change to after setting listen socket, or -1.
+<dt><b>options</b>
+<dd>0, or LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK
 </dl>
 <h3>Description</h3>
 <blockquote>
@@ -340,7 +342,8 @@ Many protocols won't care becuse their packets are always small.
 <i>const char *</i> <b>path</b>,
 <i>const char *</i> <b>host</b>,
 <i>const char *</i> <b>origin</b>,
-<i>const char *</i> <b>protocol</b>)
+<i>const char *</i> <b>protocol</b>,
+<i>int</i> <b>ietf_version_or_minus_one</b>)
 <h3>Arguments</h3>
 <dl>
 <dt><b>this</b>
@@ -362,6 +365,9 @@ signed certs
 <dd>Comma-separated list of protocols being asked for from
 the server, or just one.  The server will pick the one it
 likes best.
+<dt><b>ietf_version_or_minus_one</b>
+<dd>-1 to ask to connect using the default, latest
+protocol supported, or the specific protocol ordinal
 </dl>
 <h3>Description</h3>
 <blockquote>
index 59595e0..3508a52 100644 (file)
@@ -158,6 +158,7 @@ static struct option options[] = {
        { "port",       required_argument,      NULL, 'p' },
        { "ssl",        no_argument,            NULL, 's' },
        { "killmask",   no_argument,            NULL, 'k' },
+       { "version",    required_argument,      NULL, 'v' },
        { NULL, 0, 0, 0 }
 };
 
@@ -171,6 +172,7 @@ int main(int argc, char **argv)
        const char *address;
        struct libwebsocket *wsi_dumb;
        struct libwebsocket *wsi_mirror;
+       int ietf_version = -1; /* latest */
 
        fprintf(stderr, "libwebsockets test client\n"
                        "(C) Copyright 2010 Andy Green <andy@warmcat.com> "
@@ -179,10 +181,8 @@ int main(int argc, char **argv)
        if (argc < 2)
                goto usage;
 
-       optind++;
-
        while (n >= 0) {
-               n = getopt_long(argc, argv, "khsp:", options, NULL);
+               n = getopt_long(argc, argv, "v:khsp:", options, NULL);
                if (n < 0)
                        continue;
                switch (n) {
@@ -195,6 +195,9 @@ int main(int argc, char **argv)
                case 'k':
                        opts = LWS_WRITE_CLIENT_IGNORE_XOR_MASK;
                        break;
+               case 'v':
+                       ietf_version = atoi(optarg);
+                       break;
                case 'h':
                        goto usage;
                }
@@ -225,7 +228,7 @@ int main(int argc, char **argv)
 
        wsi_dumb = libwebsocket_client_connect(context, address, port, use_ssl,
                        "/", argv[optind], argv[optind],
-                                      protocols[PROTOCOL_DUMB_INCREMENT].name);
+                        protocols[PROTOCOL_DUMB_INCREMENT].name, ietf_version);
 
        if (wsi_dumb == NULL) {
                fprintf(stderr, "libwebsocket dumb connect failed\n");
@@ -236,7 +239,7 @@ int main(int argc, char **argv)
 
        wsi_mirror = libwebsocket_client_connect(context, address, port,
             use_ssl,  "/", argv[optind], argv[optind],
-                                      protocols[PROTOCOL_LWS_MIRROR].name);
+                            protocols[PROTOCOL_LWS_MIRROR].name, ietf_version);
 
        if (wsi_mirror == NULL) {
                fprintf(stderr, "libwebsocket dumb connect failed\n");
index e1cb0ad..25a3226 100644 (file)
@@ -277,6 +277,7 @@ static struct option options[] = {
        { "mirror",     no_argument,            NULL, 'm' },
        { "replicate",  required_argument,      NULL, 'r' },
        { "killmask",   no_argument,            NULL, 'k' },
+       { "version",    required_argument,      NULL, 'v' },
        { NULL, 0, 0, 0 }
 };
 
@@ -310,6 +311,7 @@ int main(int argc, char **argv)
        struct winsize w;
        unsigned long oldus = 0;
        unsigned long l;
+       int ietf_version = -1;
 
        if (argc < 2)
                goto usage;
@@ -318,7 +320,7 @@ int main(int argc, char **argv)
        optind++;
 
        while (n >= 0) {
-               n = getopt_long(argc, argv, "kr:hmfts:n:i:p:", options, NULL);
+               n = getopt_long(argc, argv, "v:kr:hmfts:n:i:p:", options, NULL);
                if (n < 0)
                        continue;
                switch (n) {
@@ -356,6 +358,9 @@ int main(int argc, char **argv)
                case 'k':
                        write_options = LWS_WRITE_CLIENT_IGNORE_XOR_MASK;
                        break;
+               case 'v':
+                       ietf_version = atoi(optarg);
+                       break;
 
                case 'h':
                        goto usage;
@@ -393,8 +398,9 @@ int main(int argc, char **argv)
 
        for (n = 0; n < clients; n++) {
                wsi[n] = libwebsocket_client_connect(context, address, port,
-                       use_ssl, "/", libwebsocket_canonical_hostname(context),
-                                "origin", protocols[PROTOCOL_LWS_MIRROR].name);
+                                                    use_ssl, "/", address,
+                                "origin", protocols[PROTOCOL_LWS_MIRROR].name,
+                                                                 ietf_version);
                if (wsi[n] == NULL) {
                        fprintf(stderr, "client connnection %d failed to "
                                                                "connect\n", n);