diff --git a/lib/client-handshake.c b/lib/client-handshake.c index d168084e..f4668bc1 100644 --- a/lib/client-handshake.c +++ b/lib/client-handshake.c @@ -207,10 +207,10 @@ libwebsocket_client_connect(struct libwebsocket_context *context, ietf_version_or_minus_one = SPEC_LATEST_SUPPORTED; wsi->ietf_spec_revision = ietf_version_or_minus_one; - wsi->name_buffer_pos = 0; + wsi->u.hdr.name_buffer_pos = 0; wsi->user_space = NULL; wsi->state = WSI_STATE_CLIENT_UNCONNECTED; - wsi->pings_vs_pongs = 0; + wsi->u.ws.pings_vs_pongs = 0; wsi->protocol = NULL; wsi->pending_timeout = NO_PENDING_TIMEOUT; #ifndef LWS_NO_EXTENSIONS diff --git a/lib/client-parser.c b/lib/client-parser.c index ba061475..bb96e9b8 100644 --- a/lib/client-parser.c +++ b/lib/client-parser.c @@ -43,13 +43,13 @@ int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c) switch (wsi->ietf_spec_revision) { case 13: - wsi->opcode = c & 0xf; - wsi->rsv = (c & 0x70); - wsi->final = !!((c >> 7) & 1); - switch (wsi->opcode) { + wsi->u.ws.opcode = c & 0xf; + wsi->u.ws.rsv = (c & 0x70); + wsi->u.ws.final = !!((c >> 7) & 1); + switch (wsi->u.ws.opcode) { case LWS_WS_OPCODE_07__TEXT_FRAME: case LWS_WS_OPCODE_07__BINARY_FRAME: - wsi->frame_is_binary = wsi->opcode == LWS_WS_OPCODE_07__BINARY_FRAME; + wsi->u.ws.frame_is_binary = wsi->u.ws.opcode == LWS_WS_OPCODE_07__BINARY_FRAME; break; } wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN; @@ -66,24 +66,24 @@ int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c) case LWS_RXPS_04_FRAME_HDR_LEN: - wsi->this_frame_masked = !!(c & 0x80); + wsi->u.ws.this_frame_masked = !!(c & 0x80); switch (c & 0x7f) { case 126: /* control frames are not allowed to have big lengths */ - if (wsi->opcode & 8) + if (wsi->u.ws.opcode & 8) goto illegal_ctl_length; wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_2; break; case 127: /* control frames are not allowed to have big lengths */ - if (wsi->opcode & 8) + if (wsi->u.ws.opcode & 8) goto illegal_ctl_length; wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_8; break; default: - wsi->rx_packet_length = c; - if (wsi->this_frame_masked) + wsi->u.ws.rx_packet_length = c; + if (wsi->u.ws.this_frame_masked) wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_1; else { @@ -100,17 +100,17 @@ int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c) break; case LWS_RXPS_04_FRAME_HDR_LEN16_2: - wsi->rx_packet_length = c << 8; + wsi->u.ws.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: - wsi->rx_packet_length |= c; - if (wsi->this_frame_masked) + wsi->u.ws.rx_packet_length |= c; + if (wsi->u.ws.this_frame_masked) wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_1; else { - if (wsi->rx_packet_length) + if (wsi->u.ws.rx_packet_length) wsi->lws_rx_parse_state = LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED; else { @@ -127,56 +127,56 @@ int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c) return -1; } #if defined __LP64__ - wsi->rx_packet_length = ((size_t)c) << 56; + wsi->u.ws.rx_packet_length = ((size_t)c) << 56; #else - wsi->rx_packet_length = 0; + wsi->u.ws.rx_packet_length = 0; #endif wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_7; break; case LWS_RXPS_04_FRAME_HDR_LEN64_7: #if defined __LP64__ - wsi->rx_packet_length |= ((size_t)c) << 48; + wsi->u.ws.rx_packet_length |= ((size_t)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)c) << 40; + wsi->u.ws.rx_packet_length |= ((size_t)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)c) << 32; + wsi->u.ws.rx_packet_length |= ((size_t)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)c) << 24; + wsi->u.ws.rx_packet_length |= ((size_t)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)c) << 16; + wsi->u.ws.rx_packet_length |= ((size_t)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)c) << 8; + wsi->u.ws.rx_packet_length |= ((size_t)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)c; - if (wsi->this_frame_masked) + wsi->u.ws.rx_packet_length |= (size_t)c; + if (wsi->u.ws.this_frame_masked) wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_1; else { - if (wsi->rx_packet_length) + if (wsi->u.ws.rx_packet_length) wsi->lws_rx_parse_state = LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED; else { @@ -187,32 +187,32 @@ int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c) break; case LWS_RXPS_07_COLLECT_FRAME_KEY_1: - wsi->frame_masking_nonce_04[0] = c; + wsi->u.ws.frame_masking_nonce_04[0] = c; if (c) - wsi->all_zero_nonce = 0; + wsi->u.ws.all_zero_nonce = 0; wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_2; break; case LWS_RXPS_07_COLLECT_FRAME_KEY_2: - wsi->frame_masking_nonce_04[1] = c; + wsi->u.ws.frame_masking_nonce_04[1] = c; if (c) - wsi->all_zero_nonce = 0; + wsi->u.ws.all_zero_nonce = 0; wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_3; break; case LWS_RXPS_07_COLLECT_FRAME_KEY_3: - wsi->frame_masking_nonce_04[2] = c; + wsi->u.ws.frame_masking_nonce_04[2] = c; if (c) - wsi->all_zero_nonce = 0; + wsi->u.ws.all_zero_nonce = 0; wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_4; break; case LWS_RXPS_07_COLLECT_FRAME_KEY_4: - wsi->frame_masking_nonce_04[3] = c; + wsi->u.ws.frame_masking_nonce_04[3] = c; if (c) - wsi->all_zero_nonce = 0; + wsi->u.ws.all_zero_nonce = 0; - if (wsi->rx_packet_length) + if (wsi->u.ws.rx_packet_length) wsi->lws_rx_parse_state = LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED; else { @@ -222,19 +222,19 @@ int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c) break; case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED: - if ((!wsi->this_frame_masked) || wsi->all_zero_nonce) - wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING + - (wsi->rx_user_buffer_head++)] = c; + if ((!wsi->u.ws.this_frame_masked) || wsi->u.ws.all_zero_nonce) + wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING + + (wsi->u.ws.rx_user_buffer_head++)] = c; else - wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING + - (wsi->rx_user_buffer_head++)] = - c ^ wsi->frame_masking_nonce_04[(wsi->frame_mask_index++) & 3]; + wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING + + (wsi->u.ws.rx_user_buffer_head++)] = + c ^ wsi->u.ws.frame_masking_nonce_04[(wsi->u.ws.frame_mask_index++) & 3]; - if (--wsi->rx_packet_length == 0) { + if (--wsi->u.ws.rx_packet_length == 0) { wsi->lws_rx_parse_state = LWS_RXPS_NEW; goto spill; } - if (wsi->rx_user_buffer_head != MAX_USER_RX_BUFFER) + if (wsi->u.ws.rx_user_buffer_head != MAX_USER_RX_BUFFER) break; spill: @@ -245,7 +245,7 @@ spill: * layer? If so service it and hide it from the user callback */ - switch (wsi->opcode) { + switch (wsi->u.ws.opcode) { case LWS_WS_OPCODE_07__CLOSE: /* is this an acknowledgement of our close? */ if (wsi->state == WSI_STATE_AWAITING_CLOSE_ACK) { @@ -256,11 +256,11 @@ spill: lwsl_parser("seen server's close ack\n"); return -1; } - lwsl_parser("client sees server close packet len = %d\n", wsi->rx_user_buffer_head); + lwsl_parser("client sees server close packet len = %d\n", wsi->u.ws.rx_user_buffer_head); /* parrot the close packet payload back */ n = libwebsocket_write(wsi, (unsigned char *) - &wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING], - wsi->rx_user_buffer_head, LWS_WRITE_CLOSE); + &wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING], + wsi->u.ws.rx_user_buffer_head, LWS_WRITE_CLOSE); lwsl_parser("client writing close ack returned %d\n", n); wsi->state = WSI_STATE_RETURNED_CLOSE_ALREADY; /* close the connection */ @@ -270,17 +270,17 @@ spill: lwsl_info("client received ping, doing pong\n"); /* 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); + &wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING], + wsi->u.ws.rx_user_buffer_head, LWS_WRITE_PONG); handled = 1; break; case LWS_WS_OPCODE_07__PONG: lwsl_info("client receied pong\n"); - lwsl_hexdump(&wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING], - wsi->rx_user_buffer_head); + lwsl_hexdump(&wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING], + wsi->u.ws.rx_user_buffer_head); /* keep the statistics... */ - wsi->pings_vs_pongs--; + wsi->u.ws.pings_vs_pongs--; /* issue it */ callback_action = LWS_CALLBACK_CLIENT_RECEIVE_PONG; @@ -293,7 +293,7 @@ spill: default: - lwsl_parser("Reserved opcode 0x%2X\n", wsi->opcode); + lwsl_parser("Reserved opcode 0x%2X\n", wsi->u.ws.opcode); #ifndef LWS_NO_EXTENSIONS /* * It's something special we can't understand here. @@ -301,9 +301,9 @@ spill: * state machine. */ - eff_buf.token = &wsi->rx_user_buffer[ + eff_buf.token = &wsi->u.ws.rx_user_buffer[ LWS_SEND_BUFFER_PRE_PADDING]; - eff_buf.token_len = wsi->rx_user_buffer_head; + eff_buf.token_len = wsi->u.ws.rx_user_buffer_head; for (n = 0; n < wsi->count_active_extensions; n++) { m = wsi->active_extensions[n]->callback( @@ -321,8 +321,8 @@ spill: { #endif lwsl_ext("Unhandled extended opcode " - "0x%x - ignoring frame\n", wsi->opcode); - wsi->rx_user_buffer_head = 0; + "0x%x - ignoring frame\n", wsi->u.ws.opcode); + wsi->u.ws.rx_user_buffer_head = 0; return 0; } @@ -338,9 +338,9 @@ spill: if (handled) goto already_done; - eff_buf.token = &wsi->rx_user_buffer[ + eff_buf.token = &wsi->u.ws.rx_user_buffer[ LWS_SEND_BUFFER_PRE_PADDING]; - eff_buf.token_len = wsi->rx_user_buffer_head; + eff_buf.token_len = wsi->u.ws.rx_user_buffer_head; #ifndef LWS_NO_EXTENSIONS for (n = 0; n < wsi->count_active_extensions; n++) { m = wsi->active_extensions[n]->callback( @@ -373,7 +373,7 @@ spill: } } already_done: - wsi->rx_user_buffer_head = 0; + wsi->u.ws.rx_user_buffer_head = 0; break; default: lwsl_err("client rx illegal state\n"); diff --git a/lib/client.c b/lib/client.c index a1146c00..abcd1665 100644 --- a/lib/client.c +++ b/lib/client.c @@ -201,8 +201,8 @@ int lws_client_socket_service(struct libwebsocket_context *context, struct libwe return 0; } - wsi->parser_state = WSI_TOKEN_NAME_PART; - wsi->lextable_pos = 0; + wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART; + wsi->u.hdr.lextable_pos = 0; wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY; libwebsocket_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE, AWAITING_TIMEOUT); @@ -243,7 +243,7 @@ int lws_client_socket_service(struct libwebsocket_context *context, struct libwe */ len = 1; - while (wsi->parser_state != WSI_PARSING_COMPLETE && len > 0) { + while (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE && len > 0) { #ifdef LWS_OPENSSL_SUPPORT if (wsi->use_ssl) len = SSL_read(wsi->ssl, &c, 1); @@ -260,7 +260,7 @@ int lws_client_socket_service(struct libwebsocket_context *context, struct libwe * not complete just wait for next packet coming in this state */ - if (wsi->parser_state != WSI_PARSING_COMPLETE) + if (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE) break; /* @@ -540,11 +540,11 @@ check_accept: */ if (strcmp(wsi->utf8_token[WSI_TOKEN_ACCEPT].token, - wsi->initial_handshake_hash_base64)) { + wsi->u.hdr.initial_handshake_hash_base64)) { lwsl_warn("libwebsocket_client_handshake server " "sent bad ACCEPT '%s' vs computed '%s'\n", wsi->utf8_token[WSI_TOKEN_ACCEPT].token, - wsi->initial_handshake_hash_base64); + wsi->u.hdr.initial_handshake_hash_base64); goto bail2; } @@ -562,6 +562,9 @@ check_accept: wsi->state = WSI_STATE_ESTABLISHED; wsi->mode = LWS_CONNMODE_WS_CLIENT; + /* union transition */ + memset(&wsi->u, 0, sizeof wsi->u); + lwsl_debug("handshake OK for protocol %s\n", wsi->protocol->name); /* call him back to inform him he is up */ @@ -767,8 +770,8 @@ libwebsockets_generate_client_handshake(struct libwebsocket_context *context, SHA1(buf, strlen((char *)buf), (unsigned char *)hash); lws_b64_encode_string(hash, 20, - wsi->initial_handshake_hash_base64, - sizeof wsi->initial_handshake_hash_base64); + wsi->u.hdr.initial_handshake_hash_base64, + sizeof wsi->u.hdr.initial_handshake_hash_base64); /* done with these now */ diff --git a/lib/extension-deflate-frame.c b/lib/extension-deflate-frame.c index 7a8faccc..41fcd29f 100644 --- a/lib/extension-deflate-frame.c +++ b/lib/extension-deflate-frame.c @@ -92,7 +92,7 @@ bail: break; case LWS_EXT_CALLBACK_PAYLOAD_RX: - if (!(wsi->rsv & 0x40)) + if (!(wsi->u.ws.rsv & 0x40)) return 0; /* @@ -100,7 +100,7 @@ bail: */ current_payload = eff_buf->token_len; - remaining_payload = wsi->rx_packet_length; + remaining_payload = wsi->u.ws.rx_packet_length; if (remaining_payload) { total_payload = conn->buf_pre_used + current_payload + diff --git a/lib/handshake.c b/lib/handshake.c index 3a03310d..b6d3897e 100644 --- a/lib/handshake.c +++ b/lib/handshake.c @@ -63,8 +63,8 @@ libwebsocket_read(struct libwebsocket_context *context, case WSI_STATE_HTTP_ISSUING_FILE: case WSI_STATE_HTTP: wsi->state = WSI_STATE_HTTP_HEADERS; - wsi->parser_state = WSI_TOKEN_NAME_PART; - wsi->lextable_pos = 0; + wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART; + wsi->u.hdr.lextable_pos = 0; /* fallthru */ case WSI_STATE_HTTP_HEADERS: @@ -99,7 +99,7 @@ libwebsocket_read(struct libwebsocket_context *context, for (n = 0; n < len; n++) libwebsocket_parse(wsi, *buf++); - if (wsi->parser_state != WSI_PARSING_COMPLETE) + if (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE) break; lwsl_parser("seem to be serving, mode is %d\n", wsi->mode); @@ -203,6 +203,9 @@ libwebsocket_read(struct libwebsocket_context *context, wsi->mode = LWS_CONNMODE_WS_SERVING; + /* union transition */ + memset(&wsi->u, 0, sizeof wsi->u); + lwsl_parser("accepted v%02d connection\n", wsi->ietf_spec_revision); #endif diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index 1d97782b..7de976f0 100644 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -156,7 +156,7 @@ libwebsocket_close_and_free_session(struct libwebsocket_context *context, if (old_state == WSI_STATE_DEAD_SOCKET) return; - wsi->close_reason = reason; + wsi->u.ws.close_reason = reason; #ifndef LWS_NO_EXTENSIONS /* @@ -337,8 +337,8 @@ just_kill_connection: if (wsi->c_address) free(wsi->c_address); #endif - if (wsi->rxflow_buffer) - free(wsi->rxflow_buffer); + if (wsi->u.ws.rxflow_buffer) + free(wsi->u.ws.rxflow_buffer); /* lwsl_info("closing fd=%d\n", wsi->sock); */ @@ -1209,15 +1209,15 @@ _libwebsocket_rx_flow_control(struct libwebsocket *wsi) struct libwebsocket_context *context = wsi->protocol->owning_server; int n; - if (!(wsi->rxflow_change_to & 2)) + if (!(wsi->u.ws.rxflow_change_to & 2)) return 0; - wsi->rxflow_change_to &= ~2; + wsi->u.ws.rxflow_change_to &= ~2; - lwsl_info("rxflow: wsi %p change_to %d\n", wsi, wsi->rxflow_change_to); + lwsl_info("rxflow: wsi %p change_to %d\n", wsi, wsi->u.ws.rxflow_change_to); /* if we're letting it come again, did we interrupt anything? */ - if ((wsi->rxflow_change_to & 1) && wsi->rxflow_buffer) { + if ((wsi->u.ws.rxflow_change_to & 1) && wsi->u.ws.rxflow_buffer) { n = libwebsocket_interpret_incoming_packet(wsi, NULL, 0); if (n < 0) { libwebsocket_close_and_free_session(context, wsi, LWS_CLOSE_STATUS_NOSTATUS); @@ -1228,12 +1228,12 @@ _libwebsocket_rx_flow_control(struct libwebsocket *wsi) return 0; } - if (wsi->rxflow_change_to & 1) + if (wsi->u.ws.rxflow_change_to & 1) context->fds[wsi->position_in_fds_table].events |= POLLIN; else context->fds[wsi->position_in_fds_table].events &= ~POLLIN; - if (wsi->rxflow_change_to & 1) + if (wsi->u.ws.rxflow_change_to & 1) /* external POLL support via protocol 0 */ context->protocols[0].callback(context, wsi, LWS_CALLBACK_SET_MODE_POLL_FD, @@ -1262,7 +1262,7 @@ _libwebsocket_rx_flow_control(struct libwebsocket *wsi) int libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable) { - wsi->rxflow_change_to = 2 | !!enable; + wsi->u.ws.rxflow_change_to = 2 | !!enable; return 0; } @@ -2152,13 +2152,13 @@ libwebsockets_broadcast(const struct libwebsocket_protocols *protocol, int libwebsocket_is_final_fragment(struct libwebsocket *wsi) { - return wsi->final; + return wsi->u.ws.final; } unsigned char libwebsocket_get_reserved_bits(struct libwebsocket *wsi) { - return wsi->rsv; + return wsi->u.ws.rsv; } void * diff --git a/lib/output.c b/lib/output.c index d16451fc..69bf4593 100644 --- a/lib/output.c +++ b/lib/output.c @@ -33,7 +33,7 @@ libwebsocket_0405_frame_mask_generate(struct libwebsocket *wsi) /* fetch the per-frame nonce */ n = libwebsockets_get_random(wsi->protocol->owning_server, - wsi->frame_masking_nonce_04, 4); + wsi->u.ws.frame_masking_nonce_04, 4); if (n != 4) { lwsl_parser("Unable to read from random device %s %d\n", SYSTEM_RANDOM_FILEPATH, n); @@ -41,7 +41,7 @@ libwebsocket_0405_frame_mask_generate(struct libwebsocket *wsi) } /* start masking from first byte of masking key buffer */ - wsi->frame_mask_index = 0; + wsi->u.ws.frame_mask_index = 0; return 0; } @@ -357,17 +357,17 @@ int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf, * we can do this because we demand post-buf */ - if (wsi->close_reason) { + if (wsi->u.ws.close_reason) { /* reason codes count as data bytes */ buf -= 2; - buf[0] = wsi->close_reason >> 8; - buf[1] = wsi->close_reason; + buf[0] = wsi->u.ws.close_reason >> 8; + buf[1] = wsi->u.ws.close_reason; len += 2; } break; case LWS_WRITE_PING: n = LWS_WS_OPCODE_07__PING; - wsi->pings_vs_pongs++; + wsi->u.ws.pings_vs_pongs++; break; case LWS_WRITE_PONG: n = LWS_WS_OPCODE_07__PONG; @@ -433,12 +433,12 @@ int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf, * in v7, just mask the payload */ for (n = 4; n < (int)len + 4; n++) - dropmask[n] = dropmask[n] ^ wsi->frame_masking_nonce_04[(wsi->frame_mask_index++) & 3]; + dropmask[n] = dropmask[n] ^ wsi->u.ws.frame_masking_nonce_04[(wsi->u.ws.frame_mask_index++) & 3]; if (dropmask) /* copy the frame nonce into place */ memcpy(dropmask, - wsi->frame_masking_nonce_04, 4); + wsi->u.ws.frame_masking_nonce_04, 4); } send_raw: @@ -503,13 +503,13 @@ int libwebsockets_serve_http_file(struct libwebsocket_context *context, char *p = buf; int n, m; - strncpy(wsi->filepath, file, sizeof wsi->filepath); - wsi->filepath[sizeof(wsi->filepath) - 1] = '\0'; + strncpy(wsi->u.http.filepath, file, sizeof wsi->u.http.filepath); + wsi->u.http.filepath[sizeof(wsi->u.http.filepath) - 1] = '\0'; #ifdef WIN32 - fd = open(wsi->filepath, O_RDONLY | _O_BINARY); + fd = open(wsi->u.http.filepath, O_RDONLY | _O_BINARY); #else - fd = open(wsi->filepath, O_RDONLY); + fd = open(wsi->u.http.filepath, O_RDONLY); #endif if (fd < 1) { p += sprintf(p, "HTTP/1.0 400 Bad\x0d\x0a" @@ -523,7 +523,7 @@ int libwebsockets_serve_http_file(struct libwebsocket_context *context, } fstat(fd, &stat_buf); - wsi->filelen = stat_buf.st_size; + wsi->u.http.filelen = stat_buf.st_size; p += sprintf(p, "HTTP/1.0 200 OK\x0d\x0a" "Server: libwebsockets\x0d\x0a" "Content-Type: %s\x0d\x0a" @@ -537,14 +537,14 @@ int libwebsockets_serve_http_file(struct libwebsocket_context *context, return n; } - wsi->filepos = 0; + wsi->u.http.filepos = 0; wsi->state = WSI_STATE_HTTP_ISSUING_FILE; while (!lws_send_pipe_choked(wsi)) { n = read(fd, buf, sizeof buf); if (n > 0) { - wsi->filepos += n; + wsi->u.http.filepos += n; m = libwebsocket_write(wsi, (unsigned char *)buf, n, LWS_WRITE_HTTP); if (m) { close(fd); @@ -557,13 +557,13 @@ int libwebsockets_serve_http_file(struct libwebsocket_context *context, return -1; } - if (n < sizeof(buf) || wsi->filepos == wsi->filelen) { + if (n < sizeof(buf) || wsi->u.http.filepos == wsi->u.http.filelen) { /* oh, we were able to finish here! */ wsi->state = WSI_STATE_HTTP; close(fd); if (wsi->protocol->callback(context, wsi, LWS_CALLBACK_HTTP_FILE_COMPLETION, wsi->user_space, - wsi->filepath, wsi->filepos)) { + wsi->u.http.filepath, wsi->u.http.filepos)) { lwsl_info("closing connecton after file_completion returned nonzero\n"); libwebsocket_close_and_free_session(context, wsi, LWS_CLOSE_STATUS_NOSTATUS); } @@ -590,20 +590,20 @@ int libwebsockets_serve_http_file_fragment(struct libwebsocket_context *context, int n; #ifdef WIN32 - fd = open(wsi->filepath, O_RDONLY | _O_BINARY); + fd = open(wsi->u.http.filepath, O_RDONLY | _O_BINARY); #else - fd = open(wsi->filepath, O_RDONLY); + fd = open(wsi->u.http.filepath, O_RDONLY); #endif if (fd < 1) return -1; - lseek(fd, wsi->filepos, SEEK_SET); + lseek(fd, wsi->u.http.filepos, SEEK_SET); while (!lws_send_pipe_choked(wsi)) { n = read(fd, buf, sizeof buf); if (n > 0) { libwebsocket_write(wsi, (unsigned char *)buf, n, LWS_WRITE_HTTP); - wsi->filepos += n; + wsi->u.http.filepos += n; } if (n < 0) { @@ -611,7 +611,7 @@ int libwebsockets_serve_http_file_fragment(struct libwebsocket_context *context, return -1; } - if (n < sizeof(buf) || wsi->filepos == wsi->filelen) { + if (n < sizeof(buf) || wsi->u.http.filepos == wsi->u.http.filelen) { wsi->state = WSI_STATE_HTTP; close(fd); return 0; diff --git a/lib/parsers.c b/lib/parsers.c index ea3a0ad8..1027cb92 100644 --- a/lib/parsers.c +++ b/lib/parsers.c @@ -313,7 +313,7 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c) { int n; - switch (wsi->parser_state) { + switch (wsi->u.hdr.parser_state) { case WSI_TOKEN_GET_URI: case WSI_TOKEN_HOST: case WSI_TOKEN_CONNECTION: @@ -333,76 +333,76 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c) case WSI_TOKEN_HTTP: case WSI_TOKEN_MUXURL: - lwsl_parser("WSI_TOKEN_(%d) '%c'\n", wsi->parser_state, c); + lwsl_parser("WSI_TOKEN_(%d) '%c'\n", wsi->u.hdr.parser_state, c); /* collect into malloc'd buffers */ /* optional space swallow */ - if (!wsi->utf8_token[wsi->parser_state].token_len && c == ' ') + if (!wsi->utf8_token[wsi->u.hdr.parser_state].token_len && c == ' ') break; /* special case space terminator for get-uri */ - if (wsi->parser_state == WSI_TOKEN_GET_URI && c == ' ') { - wsi->utf8_token[wsi->parser_state].token[ - wsi->utf8_token[wsi->parser_state].token_len] = '\0'; -// lwsl_parser("uri '%s'\n", wsi->utf8_token[wsi->parser_state].token); - wsi->parser_state = WSI_TOKEN_SKIPPING; + if (wsi->u.hdr.parser_state == WSI_TOKEN_GET_URI && c == ' ') { + wsi->utf8_token[wsi->u.hdr.parser_state].token[ + wsi->utf8_token[wsi->u.hdr.parser_state].token_len] = '\0'; +// lwsl_parser("uri '%s'\n", wsi->utf8_token[wsi->u.hdr.parser_state].token); + wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING; break; } /* allocate appropriate memory */ - if (wsi->utf8_token[wsi->parser_state].token_len == - wsi->current_alloc_len - 1) { + if (wsi->utf8_token[wsi->u.hdr.parser_state].token_len == + wsi->u.hdr.current_alloc_len - 1) { /* need to extend */ - wsi->current_alloc_len += LWS_ADDITIONAL_HDR_ALLOC; - if (wsi->current_alloc_len >= LWS_MAX_HEADER_LEN) { + wsi->u.hdr.current_alloc_len += LWS_ADDITIONAL_HDR_ALLOC; + if (wsi->u.hdr.current_alloc_len >= LWS_MAX_HEADER_LEN) { /* it's waaay to much payload, fail it */ - strcpy(wsi->utf8_token[wsi->parser_state].token, + strcpy(wsi->utf8_token[wsi->u.hdr.parser_state].token, "!!! Length exceeded maximum supported !!!"); - wsi->parser_state = WSI_TOKEN_SKIPPING; + wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING; break; } - wsi->utf8_token[wsi->parser_state].token = (char *) - realloc(wsi->utf8_token[wsi->parser_state].token, - wsi->current_alloc_len); - if (wsi->utf8_token[wsi->parser_state].token == NULL) { + wsi->utf8_token[wsi->u.hdr.parser_state].token = (char *) + realloc(wsi->utf8_token[wsi->u.hdr.parser_state].token, + wsi->u.hdr.current_alloc_len); + if (wsi->utf8_token[wsi->u.hdr.parser_state].token == NULL) { lwsl_err("Out of mem\n"); return -1; } } /* bail at EOL */ - if (wsi->parser_state != WSI_TOKEN_CHALLENGE && c == '\x0d') { - wsi->utf8_token[wsi->parser_state].token[ - wsi->utf8_token[wsi->parser_state].token_len] = '\0'; - wsi->parser_state = WSI_TOKEN_SKIPPING_SAW_CR; + if (wsi->u.hdr.parser_state != WSI_TOKEN_CHALLENGE && c == '\x0d') { + wsi->utf8_token[wsi->u.hdr.parser_state].token[ + wsi->utf8_token[wsi->u.hdr.parser_state].token_len] = '\0'; + wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING_SAW_CR; lwsl_parser("*\n"); break; } - wsi->utf8_token[wsi->parser_state].token[ - wsi->utf8_token[wsi->parser_state].token_len++] = c; + wsi->utf8_token[wsi->u.hdr.parser_state].token[ + wsi->utf8_token[wsi->u.hdr.parser_state].token_len++] = c; /* per-protocol end of headers management */ - if (wsi->parser_state != WSI_TOKEN_CHALLENGE) + if (wsi->u.hdr.parser_state != WSI_TOKEN_CHALLENGE) break; /* -76 has no version header ... server */ if (!wsi->utf8_token[WSI_TOKEN_VERSION].token_len && wsi->mode != LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY && - wsi->utf8_token[wsi->parser_state].token_len != 8) + wsi->utf8_token[wsi->u.hdr.parser_state].token_len != 8) break; /* -76 has no version header ... client */ if (!wsi->utf8_token[WSI_TOKEN_VERSION].token_len && wsi->mode == LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY && - wsi->utf8_token[wsi->parser_state].token_len != 16) + wsi->utf8_token[wsi->u.hdr.parser_state].token_len != 16) break; /* <= 03 has old handshake with version header needs 8 bytes */ if (wsi->utf8_token[WSI_TOKEN_VERSION].token_len && atoi(wsi->utf8_token[WSI_TOKEN_VERSION].token) < 4 && - wsi->utf8_token[wsi->parser_state].token_len != 8) + wsi->utf8_token[wsi->u.hdr.parser_state].token_len != 8) break; /* no payload challenge in 01 + */ @@ -417,40 +417,40 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c) /* For any supported protocol we have enough payload */ lwsl_parser("Setting WSI_PARSING_COMPLETE\n"); - wsi->parser_state = WSI_PARSING_COMPLETE; + wsi->u.hdr.parser_state = WSI_PARSING_COMPLETE; break; case WSI_INIT_TOKEN_MUXURL: - wsi->parser_state = WSI_TOKEN_MUXURL; - wsi->current_alloc_len = LWS_INITIAL_HDR_ALLOC; + wsi->u.hdr.parser_state = WSI_TOKEN_MUXURL; + wsi->u.hdr.current_alloc_len = LWS_INITIAL_HDR_ALLOC; - wsi->utf8_token[wsi->parser_state].token = (char *) - malloc(wsi->current_alloc_len); - if (wsi->utf8_token[wsi->parser_state].token == NULL) { + wsi->utf8_token[wsi->u.hdr.parser_state].token = (char *) + malloc(wsi->u.hdr.current_alloc_len); + if (wsi->utf8_token[wsi->u.hdr.parser_state].token == NULL) { lwsl_err("Out of mem\n"); return -1; } - wsi->utf8_token[wsi->parser_state].token_len = 0; + wsi->utf8_token[wsi->u.hdr.parser_state].token_len = 0; break; /* collecting and checking a name part */ case WSI_TOKEN_NAME_PART: lwsl_parser("WSI_TOKEN_NAME_PART '%c'\n", c); - if (wsi->name_buffer_pos == sizeof(wsi->name_buffer) - 1) { + if (wsi->u.hdr.name_buffer_pos == sizeof(wsi->u.hdr.name_buffer) - 1) { /* name bigger than we can handle, skip until next */ - wsi->parser_state = WSI_TOKEN_SKIPPING; + wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING; break; } - wsi->name_buffer[wsi->name_buffer_pos++] = c; - wsi->name_buffer[wsi->name_buffer_pos] = '\0'; + wsi->u.hdr.name_buffer[wsi->u.hdr.name_buffer_pos++] = c; + wsi->u.hdr.name_buffer[wsi->u.hdr.name_buffer_pos] = '\0'; - wsi->lextable_pos = lextable_decode(wsi->lextable_pos, c); - if (lextable[wsi->lextable_pos + 1] == 0) { + wsi->u.hdr.lextable_pos = lextable_decode(wsi->u.hdr.lextable_pos, c); + if (lextable[wsi->u.hdr.lextable_pos + 1] == 0) { - n = lextable[wsi->lextable_pos] & 0x7f; + n = lextable[wsi->u.hdr.lextable_pos] & 0x7f; - lwsl_parser("known hdr '%s'\n", wsi->name_buffer); + lwsl_parser("known hdr '%s'\n", wsi->u.hdr.name_buffer); /* * WSORIGIN is protocol equiv to ORIGIN, @@ -459,42 +459,42 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c) if (n == WSI_TOKEN_SWORIGIN) n = WSI_TOKEN_ORIGIN; - wsi->parser_state = (enum lws_token_indexes) (WSI_TOKEN_GET_URI + n); + wsi->u.hdr.parser_state = (enum lws_token_indexes) (WSI_TOKEN_GET_URI + n); n = WSI_TOKEN_COUNT; /* If the header has been seen already, just append */ - if (!wsi->utf8_token[wsi->parser_state].token) { + if (!wsi->utf8_token[wsi->u.hdr.parser_state].token) { - wsi->current_alloc_len = LWS_INITIAL_HDR_ALLOC; - wsi->utf8_token[wsi->parser_state].token = (char *) - malloc(wsi->current_alloc_len); - if (wsi->utf8_token[wsi->parser_state].token == NULL) { + wsi->u.hdr.current_alloc_len = LWS_INITIAL_HDR_ALLOC; + wsi->utf8_token[wsi->u.hdr.parser_state].token = (char *) + malloc(wsi->u.hdr.current_alloc_len); + if (wsi->utf8_token[wsi->u.hdr.parser_state].token == NULL) { lwsl_err("Out of mem\n"); return -1; } - wsi->utf8_token[wsi->parser_state].token_len = 0; + wsi->utf8_token[wsi->u.hdr.parser_state].token_len = 0; } } /* colon delimiter means we just don't know this name */ - if (wsi->parser_state == WSI_TOKEN_NAME_PART) { + if (wsi->u.hdr.parser_state == WSI_TOKEN_NAME_PART) { if (c == ':') { lwsl_parser("skipping unknown header '%s'\n", - wsi->name_buffer); - wsi->parser_state = WSI_TOKEN_SKIPPING; + wsi->u.hdr.name_buffer); + wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING; break; } if (c == ' ' && !wsi->utf8_token[WSI_TOKEN_GET_URI].token_len) { lwsl_parser("unknown method '%s'\n", - wsi->name_buffer); - wsi->parser_state = WSI_TOKEN_GET_URI; - wsi->current_alloc_len = LWS_INITIAL_HDR_ALLOC; + wsi->u.hdr.name_buffer); + wsi->u.hdr.parser_state = WSI_TOKEN_GET_URI; + wsi->u.hdr.current_alloc_len = LWS_INITIAL_HDR_ALLOC; wsi->utf8_token[WSI_TOKEN_GET_URI].token = - (char *)malloc(wsi->current_alloc_len); + (char *)malloc(wsi->u.hdr.current_alloc_len); if (wsi->utf8_token[WSI_TOKEN_GET_URI].token == NULL) { lwsl_err("Out of mem\n"); return -1; @@ -503,7 +503,7 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c) } } - if (wsi->parser_state != WSI_TOKEN_CHALLENGE) + if (wsi->u.hdr.parser_state != WSI_TOKEN_CHALLENGE) break; /* don't look for payload when it can just be http headers */ @@ -512,7 +512,7 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c) /* they're HTTP headers, not websocket upgrade! */ lwsl_parser("Setting WSI_PARSING_COMPLETE " "from http headers\n"); - wsi->parser_state = WSI_PARSING_COMPLETE; + wsi->u.hdr.parser_state = WSI_PARSING_COMPLETE; } /* 04 version has no packet content after end of hdrs */ @@ -520,7 +520,7 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c) if (wsi->utf8_token[WSI_TOKEN_VERSION].token_len && atoi(wsi->utf8_token[WSI_TOKEN_VERSION].token) >= 4) { lwsl_parser("04 header completed\n"); - wsi->parser_state = WSI_PARSING_COMPLETE; + wsi->u.hdr.parser_state = WSI_PARSING_COMPLETE; wsi->utf8_token[WSI_TOKEN_CHALLENGE].token_len = 0; free(wsi->utf8_token[WSI_TOKEN_CHALLENGE].token); wsi->utf8_token[WSI_TOKEN_CHALLENGE].token = NULL; @@ -529,7 +529,7 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c) /* client parser? */ lwsl_parser("04 header completed\n"); - wsi->parser_state = WSI_PARSING_COMPLETE; + wsi->u.hdr.parser_state = WSI_PARSING_COMPLETE; break; @@ -537,16 +537,16 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c) case WSI_TOKEN_SKIPPING: lwsl_parser("WSI_TOKEN_SKIPPING '%c'\n", c); if (c == '\x0d') - wsi->parser_state = WSI_TOKEN_SKIPPING_SAW_CR; + wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING_SAW_CR; break; case WSI_TOKEN_SKIPPING_SAW_CR: lwsl_parser("WSI_TOKEN_SKIPPING_SAW_CR '%c'\n", c); if (c == '\x0a') { - wsi->parser_state = WSI_TOKEN_NAME_PART; - wsi->lextable_pos = 0; + wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART; + wsi->u.hdr.lextable_pos = 0; } else - wsi->parser_state = WSI_TOKEN_SKIPPING; - wsi->name_buffer_pos = 0; + wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING; + wsi->u.hdr.name_buffer_pos = 0; break; /* we're done, ignore anything else */ case WSI_PARSING_COMPLETE: @@ -573,7 +573,7 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c) int lws_frame_is_binary(struct libwebsocket *wsi) { - return wsi->frame_is_binary; + return wsi->u.ws.frame_is_binary; } int @@ -598,7 +598,7 @@ libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c) /* * no prepended frame key any more */ - wsi->all_zero_nonce = 1; + wsi->u.ws.all_zero_nonce = 1; goto handle_first; default: @@ -608,28 +608,28 @@ libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c) } break; case LWS_RXPS_04_MASK_NONCE_1: - wsi->frame_masking_nonce_04[1] = c; + wsi->u.ws.frame_masking_nonce_04[1] = c; if (c) - wsi->all_zero_nonce = 0; + wsi->u.ws.all_zero_nonce = 0; wsi->lws_rx_parse_state = LWS_RXPS_04_MASK_NONCE_2; break; case LWS_RXPS_04_MASK_NONCE_2: - wsi->frame_masking_nonce_04[2] = c; + wsi->u.ws.frame_masking_nonce_04[2] = c; if (c) - wsi->all_zero_nonce = 0; + wsi->u.ws.all_zero_nonce = 0; wsi->lws_rx_parse_state = LWS_RXPS_04_MASK_NONCE_3; break; case LWS_RXPS_04_MASK_NONCE_3: - wsi->frame_masking_nonce_04[3] = c; + wsi->u.ws.frame_masking_nonce_04[3] = c; if (c) - wsi->all_zero_nonce = 0; + wsi->u.ws.all_zero_nonce = 0; /* * start from the zero'th byte in the XOR key buffer since * this is the start of a frame with a new key */ - wsi->frame_mask_index = 0; + wsi->u.ws.frame_mask_index = 0; wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_1; break; @@ -684,13 +684,13 @@ handle_first: * FIN (b7) */ - wsi->opcode = c & 0xf; - wsi->rsv = c & 0x70; - wsi->final = !!((c >> 7) & 1); - switch (wsi->opcode) { + wsi->u.ws.opcode = c & 0xf; + wsi->u.ws.rsv = c & 0x70; + wsi->u.ws.final = !!((c >> 7) & 1); + switch (wsi->u.ws.opcode) { case LWS_WS_OPCODE_07__TEXT_FRAME: case LWS_WS_OPCODE_07__BINARY_FRAME: - wsi->frame_is_binary = wsi->opcode == LWS_WS_OPCODE_07__BINARY_FRAME; + wsi->u.ws.frame_is_binary = wsi->u.ws.opcode == LWS_WS_OPCODE_07__BINARY_FRAME; break; } wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN; @@ -698,26 +698,26 @@ handle_first: case LWS_RXPS_04_FRAME_HDR_LEN: - wsi->this_frame_masked = !!(c & 0x80); + wsi->u.ws.this_frame_masked = !!(c & 0x80); switch (c & 0x7f) { case 126: /* control frames are not allowed to have big lengths */ - if (wsi->opcode & 8) + if (wsi->u.ws.opcode & 8) goto illegal_ctl_length; wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_2; break; case 127: /* control frames are not allowed to have big lengths */ - if (wsi->opcode & 8) + if (wsi->u.ws.opcode & 8) goto illegal_ctl_length; wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_8; break; default: - wsi->rx_packet_length = c & 0x7f; - if (wsi->this_frame_masked) + wsi->u.ws.rx_packet_length = c & 0x7f; + if (wsi->u.ws.this_frame_masked) wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_1; else @@ -728,13 +728,13 @@ handle_first: break; case LWS_RXPS_04_FRAME_HDR_LEN16_2: - wsi->rx_packet_length = c << 8; + wsi->u.ws.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: - wsi->rx_packet_length |= c; - if (wsi->this_frame_masked) + wsi->u.ws.rx_packet_length |= c; + if (wsi->u.ws.this_frame_masked) wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_1; else @@ -749,52 +749,52 @@ handle_first: return -1; } #if defined __LP64__ - wsi->rx_packet_length = ((size_t)c) << 56; + wsi->u.ws.rx_packet_length = ((size_t)c) << 56; #else - wsi->rx_packet_length = 0; + wsi->u.ws.rx_packet_length = 0; #endif wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_7; break; case LWS_RXPS_04_FRAME_HDR_LEN64_7: #if defined __LP64__ - wsi->rx_packet_length |= ((size_t)c) << 48; + wsi->u.ws.rx_packet_length |= ((size_t)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)c) << 40; + wsi->u.ws.rx_packet_length |= ((size_t)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)c) << 32; + wsi->u.ws.rx_packet_length |= ((size_t)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)c) << 24; + wsi->u.ws.rx_packet_length |= ((size_t)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)c) << 16; + wsi->u.ws.rx_packet_length |= ((size_t)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)c) << 8; + wsi->u.ws.rx_packet_length |= ((size_t)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)c); - if (wsi->this_frame_masked) + wsi->u.ws.rx_packet_length |= ((size_t)c); + if (wsi->u.ws.this_frame_masked) wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_1; else @@ -803,51 +803,51 @@ handle_first: break; case LWS_RXPS_07_COLLECT_FRAME_KEY_1: - wsi->frame_masking_nonce_04[0] = c; + wsi->u.ws.frame_masking_nonce_04[0] = c; if (c) - wsi->all_zero_nonce = 0; + wsi->u.ws.all_zero_nonce = 0; wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_2; break; case LWS_RXPS_07_COLLECT_FRAME_KEY_2: - wsi->frame_masking_nonce_04[1] = c; + wsi->u.ws.frame_masking_nonce_04[1] = c; if (c) - wsi->all_zero_nonce = 0; + wsi->u.ws.all_zero_nonce = 0; wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_3; break; case LWS_RXPS_07_COLLECT_FRAME_KEY_3: - wsi->frame_masking_nonce_04[2] = c; + wsi->u.ws.frame_masking_nonce_04[2] = c; if (c) - wsi->all_zero_nonce = 0; + wsi->u.ws.all_zero_nonce = 0; wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_4; break; case LWS_RXPS_07_COLLECT_FRAME_KEY_4: - wsi->frame_masking_nonce_04[3] = c; + wsi->u.ws.frame_masking_nonce_04[3] = c; if (c) - wsi->all_zero_nonce = 0; + wsi->u.ws.all_zero_nonce = 0; wsi->lws_rx_parse_state = LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED; - wsi->frame_mask_index = 0; + wsi->u.ws.frame_mask_index = 0; break; case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED: - if (wsi->all_zero_nonce) - wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING + - (wsi->rx_user_buffer_head++)] = c; + if (wsi->u.ws.all_zero_nonce) + wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING + + (wsi->u.ws.rx_user_buffer_head++)] = c; else - wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING + - (wsi->rx_user_buffer_head++)] = - c ^ wsi->frame_masking_nonce_04[(wsi->frame_mask_index++) & 3]; + wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING + + (wsi->u.ws.rx_user_buffer_head++)] = + c ^ wsi->u.ws.frame_masking_nonce_04[(wsi->u.ws.frame_mask_index++) & 3]; - if (--wsi->rx_packet_length == 0) { + if (--wsi->u.ws.rx_packet_length == 0) { wsi->lws_rx_parse_state = LWS_RXPS_NEW; goto spill; } - if (wsi->rx_user_buffer_head != MAX_USER_RX_BUFFER) + if (wsi->u.ws.rx_user_buffer_head != MAX_USER_RX_BUFFER) break; spill: /* @@ -857,7 +857,7 @@ spill: lwsl_parser("spill on %s\n", wsi->protocol->name); - switch (wsi->opcode) { + switch (wsi->u.ws.opcode) { case LWS_WS_OPCODE_07__CLOSE: /* is this an acknowledgement of our close? */ if (wsi->state == WSI_STATE_AWAITING_CLOSE_ACK) { @@ -871,8 +871,8 @@ spill: lwsl_parser("server sees client close packet\n"); /* parrot the close packet payload back */ n = libwebsocket_write(wsi, (unsigned char *) - &wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING], - wsi->rx_user_buffer_head, LWS_WRITE_CLOSE); + &wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING], + wsi->u.ws.rx_user_buffer_head, LWS_WRITE_CLOSE); if (n) lwsl_info("write of close ack failed %d\n", n); wsi->state = WSI_STATE_RETURNED_CLOSE_ALREADY; @@ -880,20 +880,20 @@ spill: return -1; case LWS_WS_OPCODE_07__PING: - lwsl_info("received %d byte ping, sending pong\n", wsi->rx_user_buffer_head); - lwsl_hexdump(&wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING], wsi->rx_user_buffer_head); + lwsl_info("received %d byte ping, sending pong\n", wsi->u.ws.rx_user_buffer_head); + lwsl_hexdump(&wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING], wsi->u.ws.rx_user_buffer_head); /* 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); + &wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING], wsi->u.ws.rx_user_buffer_head, LWS_WRITE_PONG); /* ... then just drop it */ - wsi->rx_user_buffer_head = 0; + wsi->u.ws.rx_user_buffer_head = 0; return 0; case LWS_WS_OPCODE_07__PONG: /* keep the statistics... */ - wsi->pings_vs_pongs--; + wsi->u.ws.pings_vs_pongs--; /* ... then just drop it */ - wsi->rx_user_buffer_head = 0; + wsi->u.ws.rx_user_buffer_head = 0; return 0; case LWS_WS_OPCODE_07__TEXT_FRAME: @@ -903,7 +903,7 @@ spill: default: #ifndef LWS_NO_EXTENSIONS - lwsl_parser("passing opcode %x up to exts\n", wsi->opcode); + lwsl_parser("passing opcode %x up to exts\n", wsi->u.ws.opcode); /* * It's something special we can't understand here. @@ -911,9 +911,9 @@ spill: * state machine. */ - eff_buf.token = &wsi->rx_user_buffer[ + eff_buf.token = &wsi->u.ws.rx_user_buffer[ LWS_SEND_BUFFER_PRE_PADDING]; - eff_buf.token_len = wsi->rx_user_buffer_head; + eff_buf.token_len = wsi->u.ws.rx_user_buffer_head; handled = 0; for (n = 0; n < wsi->count_active_extensions; n++) { @@ -930,9 +930,9 @@ spill: if (!handled) #endif lwsl_ext("Unhandled extended opcode " - "0x%x - ignoring frame\n", wsi->opcode); + "0x%x - ignoring frame\n", wsi->u.ws.opcode); - wsi->rx_user_buffer_head = 0; + wsi->u.ws.rx_user_buffer_head = 0; return 0; } @@ -942,9 +942,9 @@ spill: * so it can be sent straight out again using libwebsocket_write */ - eff_buf.token = &wsi->rx_user_buffer[ + eff_buf.token = &wsi->u.ws.rx_user_buffer[ LWS_SEND_BUFFER_PRE_PADDING]; - eff_buf.token_len = wsi->rx_user_buffer_head; + eff_buf.token_len = wsi->u.ws.rx_user_buffer_head; #ifndef LWS_NO_EXTENSIONS for (n = 0; n < wsi->count_active_extensions; n++) { m = wsi->active_extensions[n]->callback( @@ -975,7 +975,7 @@ spill: lwsl_err("No callback on payload spill!\n"); } - wsi->rx_user_buffer_head = 0; + wsi->u.ws.rx_user_buffer_head = 0; break; } @@ -995,7 +995,7 @@ int libwebsocket_interpret_incoming_packet(struct libwebsocket *wsi, { size_t n; int m; - int clear_rxflow = !!wsi->rxflow_buffer; + int clear_rxflow = !!wsi->u.ws.rxflow_buffer; struct libwebsocket_context *context = wsi->protocol->owning_server; #if 0 @@ -1003,17 +1003,17 @@ int libwebsocket_interpret_incoming_packet(struct libwebsocket *wsi, lwsl_hexdump(buf, len); #endif - if (buf && wsi->rxflow_buffer) + if (buf && wsi->u.ws.rxflow_buffer) lwsl_err("!!!! libwebsocket_interpret_incoming_packet: was pending rxflow, data loss\n"); /* let the rx protocol state machine have as much as it needs */ n = 0; if (!buf) { - lwsl_info("dumping stored rxflow buffer len %d pos=%d\n", wsi->rxflow_len, wsi->rxflow_pos); - buf = wsi->rxflow_buffer; - n = wsi->rxflow_pos; - len = wsi->rxflow_len; + lwsl_info("dumping stored rxflow buffer len %d pos=%d\n", wsi->u.ws.rxflow_len, wsi->u.ws.rxflow_pos); + buf = wsi->u.ws.rxflow_buffer; + n = wsi->u.ws.rxflow_pos; + len = wsi->u.ws.rxflow_len; /* let's pretend he's already allowing input */ context->fds[wsi->position_in_fds_table].events |= POLLIN; } @@ -1021,16 +1021,16 @@ int libwebsocket_interpret_incoming_packet(struct libwebsocket *wsi, while (n < len) { if (!(context->fds[wsi->position_in_fds_table].events & POLLIN)) { /* his RX is flowcontrolled */ - if (!wsi->rxflow_buffer) { /* a new rxflow in effect, buffer it and warn caller */ + if (!wsi->u.ws.rxflow_buffer) { /* a new rxflow in effect, buffer it and warn caller */ lwsl_info("new rxflow input buffer len %d\n", len - n); - wsi->rxflow_buffer = (unsigned char *)malloc(len - n); - wsi->rxflow_len = len - n; - wsi->rxflow_pos = 0; - memcpy(wsi->rxflow_buffer, buf + n, len - n); + wsi->u.ws.rxflow_buffer = (unsigned char *)malloc(len - n); + wsi->u.ws.rxflow_len = len - n; + wsi->u.ws.rxflow_pos = 0; + memcpy(wsi->u.ws.rxflow_buffer, buf + n, len - n); } else { lwsl_info("re-using rxflow input buffer\n"); /* rxflow while we were spilling previous rxflow buffer */ - wsi->rxflow_pos = n; + wsi->u.ws.rxflow_pos = n; } return 1; } @@ -1042,8 +1042,8 @@ int libwebsocket_interpret_incoming_packet(struct libwebsocket *wsi, if (clear_rxflow) { lwsl_info("flow: clearing it\n"); - free(wsi->rxflow_buffer); - wsi->rxflow_buffer = NULL; + free(wsi->u.ws.rxflow_buffer); + wsi->u.ws.rxflow_buffer = NULL; context->fds[wsi->position_in_fds_table].events &= ~POLLIN; } @@ -1071,5 +1071,5 @@ int libwebsocket_interpret_incoming_packet(struct libwebsocket *wsi, size_t libwebsockets_remaining_packet_payload(struct libwebsocket *wsi) { - return wsi->rx_packet_length; + return wsi->u.ws.rx_packet_length; } diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index 34913848..664f188b 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -273,7 +273,50 @@ enum pending_timeout { * other APIs to get information out of it. */ +struct _lws_http_mode_related { + char filepath[PATH_MAX]; + unsigned long filepos; + unsigned long filelen; +}; + +struct _lws_header_related { + char name_buffer[LWS_MAX_HEADER_NAME_LENGTH]; + int name_buffer_pos; + int lextable_pos; + enum lws_token_indexes parser_state; + int current_alloc_len; +#ifndef LWS_NO_CLIENT + char initial_handshake_hash_base64[30]; +#endif +}; + +struct _lws_websocket_related { + char rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING + MAX_USER_RX_BUFFER + + LWS_SEND_BUFFER_POST_PADDING]; + int rx_user_buffer_head; + unsigned char masking_key_04[20]; + unsigned char frame_masking_nonce_04[4]; + unsigned char frame_mask_04[20]; + unsigned char frame_mask_index; + size_t rx_packet_length; + unsigned char opcode; + unsigned char final; + unsigned char rsv; + int frame_is_binary:1; + int pings_vs_pongs; + char all_zero_nonce; + enum lws_close_status close_reason; + unsigned char *rxflow_buffer; + int rxflow_len; + int rxflow_pos; + int rxflow_change_to; + char this_frame_masked; +}; + struct libwebsocket { + + /* lifetime members */ + const struct libwebsocket_protocols *protocol; #ifndef LWS_NO_EXTENSIONS struct libwebsocket_extension * @@ -284,59 +327,36 @@ struct libwebsocket { struct libwebsocket *extension_handles; struct libwebsocket *candidate_children_list; #endif - enum lws_connection_states state; - - char name_buffer[LWS_MAX_HEADER_NAME_LENGTH]; - int name_buffer_pos; - int lextable_pos; - int current_alloc_len; - enum lws_token_indexes parser_state; - struct lws_tokens utf8_token[WSI_TOKEN_COUNT]; int ietf_spec_revision; - char rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING + MAX_USER_RX_BUFFER + - LWS_SEND_BUFFER_POST_PADDING]; - int rx_user_buffer_head; - enum libwebsocket_write_protocol rx_frame_type; -#ifndef LWS_NO_FORK - int protocol_index_for_broadcast_proxy; -#endif + + enum connection_mode mode; + enum lws_connection_states state; + enum lws_rx_parse_state lws_rx_parse_state; + enum pending_timeout pending_timeout; unsigned long pending_timeout_limit; int sock; int position_in_fds_table; - unsigned char *rxflow_buffer; - int rxflow_len; - int rxflow_pos; - int rxflow_change_to; - enum lws_rx_parse_state lws_rx_parse_state; + void *user_space; - /* 04 protocol specific */ + /* members with mutually exclusive lifetimes are unionized */ - unsigned char masking_key_04[20]; - unsigned char frame_masking_nonce_04[4]; - unsigned char frame_mask_04[20]; - unsigned char frame_mask_index; - size_t rx_packet_length; - unsigned char opcode; - unsigned char final; - unsigned char rsv; - int frame_is_binary:1; + union u { + struct _lws_http_mode_related http; + struct _lws_header_related hdr; + struct _lws_websocket_related ws; + } u; - int pings_vs_pongs; - char all_zero_nonce; - - enum lws_close_status close_reason; - - /* 07 specific */ - char this_frame_masked; - - enum connection_mode mode; + struct lws_tokens utf8_token[WSI_TOKEN_COUNT]; + + enum libwebsocket_write_protocol rx_frame_type; +#ifndef LWS_NO_FORK + int protocol_index_for_broadcast_proxy; +#endif #ifndef LWS_NO_CLIENT - /* client support */ - char initial_handshake_hash_base64[30]; char *c_path; char *c_host; char *c_origin; @@ -351,14 +371,7 @@ struct libwebsocket { SSL *ssl; BIO *client_bio; int use_ssl; -#endif - - /* http send file */ - char filepath[PATH_MAX]; - unsigned long filepos; - unsigned long filelen; - - void *user_space; +#endif }; extern int diff --git a/lib/server-handshake.c b/lib/server-handshake.c index 2a0e886a..6fd94485 100644 --- a/lib/server-handshake.c +++ b/lib/server-handshake.c @@ -257,7 +257,7 @@ handshake_0405(struct libwebsocket_context *context, struct libwebsocket *wsi) free(response); wsi->state = WSI_STATE_ESTABLISHED; wsi->lws_rx_parse_state = LWS_RXPS_NEW; - wsi->rx_packet_length = 0; + wsi->u.ws.rx_packet_length = 0; /* notify user code that we're ready to roll */ diff --git a/lib/server.c b/lib/server.c index 4134d48f..7c037b22 100644 --- a/lib/server.c +++ b/lib/server.c @@ -102,7 +102,7 @@ libwebsocket_create_new_server_wsi(struct libwebsocket_context *context) /* intialize the instance struct */ new_wsi->state = WSI_STATE_HTTP; - new_wsi->name_buffer_pos = 0; + new_wsi->u.hdr.name_buffer_pos = 0; new_wsi->mode = LWS_CONNMODE_HTTP_SERVING; for (n = 0; n < WSI_TOKEN_COUNT; n++) { @@ -196,7 +196,7 @@ int lws_server_socket_service(struct libwebsocket_context *context, else if (wsi->state == WSI_STATE_HTTP && wsi->protocol->callback) if (user_callback_handle_rxflow(wsi->protocol->callback, context, wsi, LWS_CALLBACK_HTTP_FILE_COMPLETION, wsi->user_space, - wsi->filepath, wsi->filepos)) + wsi->u.http.filepath, wsi->u.http.filepos)) libwebsocket_close_and_free_session(context, wsi, LWS_CLOSE_STATUS_NOSTATUS); break;