1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

add 07 support

Signed-off-by: Andy Green <andy@warmcat.com>
This commit is contained in:
Andy Green 2011-04-24 05:46:23 +01:00
parent 5fd55cd3a9
commit 283d0a2046
2 changed files with 157 additions and 23 deletions

View file

@ -297,6 +297,16 @@ static int libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
wsi->all_zero_nonce = 0;
wsi->lws_rx_parse_state = LWS_RXPS_04_MASK_NONCE_1;
break;
case 7:
/*
* no prepended frame key any more
*/
wsi->all_zero_nonce = 1;
wsi->frame_masking_nonce_04[0] = c;
if (c)
wsi->all_zero_nonce = 0;
goto handle_first;
default:
fprintf(stderr, "libwebsocket_rx_sm doesn't know "
"about spec version %d\n", wsi->ietf_spec_revision);
@ -393,6 +403,8 @@ post_mask:
*/
case LWS_RXPS_04_FRAME_HDR_1:
handle_first:
/*
* 04 spec defines the opcode like this: (1, 2, and 3 are
* "control frame" opcodes which may not be fragmented or
@ -410,7 +422,8 @@ post_mask:
* FIN (b7)
*/
c = wsi->xor_mask(wsi, c);
if (wsi->ietf_spec_revision < 7)
c = wsi->xor_mask(wsi, c);
if (c & 0x70) {
fprintf(stderr,
@ -426,15 +439,19 @@ post_mask:
break;
case LWS_RXPS_04_FRAME_HDR_LEN:
c = wsi->xor_mask(wsi, c);
if (c & 0x80) {
if (wsi->ietf_spec_revision < 7)
c = wsi->xor_mask(wsi, c);
if ((c & 0x80) && wsi->ietf_spec_revision < 7) {
fprintf(stderr, "Frame has extensions "
"set illegally 2\n");
/* kill the connection */
return -1;
}
wsi->this_frame_masked = !!(c & 0x80);
switch (c) {
case 126:
/* control frames are not allowed to have big lengths */
@ -468,29 +485,40 @@ post_mask:
break;
default:
wsi->rx_packet_length = c;
wsi->lws_rx_parse_state =
if (wsi->this_frame_masked)
wsi->lws_rx_parse_state =
LWS_RXPS_07_COLLECT_FRAME_KEY_1;
else
wsi->lws_rx_parse_state =
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
break;
}
break;
case LWS_RXPS_04_FRAME_HDR_LEN16_2:
c = wsi->xor_mask(wsi, c);
if (wsi->ietf_spec_revision < 7)
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 = wsi->xor_mask(wsi, c);
if (wsi->ietf_spec_revision < 7)
c = wsi->xor_mask(wsi, c);
wsi->rx_packet_length |= c;
wsi->lws_rx_parse_state =
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
if (wsi->this_frame_masked)
wsi->lws_rx_parse_state =
LWS_RXPS_07_COLLECT_FRAME_KEY_1;
else
wsi->lws_rx_parse_state =
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
break;
case LWS_RXPS_04_FRAME_HDR_LEN64_8:
c = wsi->xor_mask(wsi, c);
if (wsi->ietf_spec_revision < 7)
c = wsi->xor_mask(wsi, c);
if (c & 0x80) {
fprintf(stderr, "b63 of length must be zero\n");
/* kill the connection */
@ -505,45 +533,63 @@ post_mask:
break;
case LWS_RXPS_04_FRAME_HDR_LEN64_7:
if (wsi->ietf_spec_revision < 7)
c = wsi->xor_mask(wsi, c);
#if defined __LP64__
wsi->rx_packet_length |= ((size_t)wsi->xor_mask(wsi, c)) << 48;
wsi->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 (wsi->ietf_spec_revision < 7)
c = wsi->xor_mask(wsi, c);
#if defined __LP64__
wsi->rx_packet_length |= ((size_t)wsi->xor_mask(wsi, c)) << 40;
wsi->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 (wsi->ietf_spec_revision < 7)
c = wsi->xor_mask(wsi, c);
#if defined __LP64__
wsi->rx_packet_length |= ((size_t)wsi->xor_mask(wsi, c)) << 32;
wsi->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)wsi->xor_mask(wsi, c)) << 24;
if (wsi->ietf_spec_revision < 7)
c = wsi->xor_mask(wsi, c);
wsi->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)wsi->xor_mask(wsi, c)) << 16;
if (wsi->ietf_spec_revision < 7)
c = wsi->xor_mask(wsi, c);
wsi->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)wsi->xor_mask(wsi, c)) << 8;
if (wsi->ietf_spec_revision < 7)
c = wsi->xor_mask(wsi, c);
wsi->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)wsi->xor_mask(wsi, c));
wsi->lws_rx_parse_state =
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
if (wsi->ietf_spec_revision < 7)
c = wsi->xor_mask(wsi, c);
wsi->rx_packet_length |= ((size_t)c);
if (wsi->this_frame_masked)
wsi->lws_rx_parse_state =
LWS_RXPS_07_COLLECT_FRAME_KEY_1;
else
wsi->lws_rx_parse_state =
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
break;
case LWS_RXPS_EAT_UNTIL_76_FF:
@ -585,6 +631,37 @@ issue:
case LWS_RXPS_PULLING_76_LENGTH:
break;
case LWS_RXPS_07_COLLECT_FRAME_KEY_1:
wsi->frame_masking_nonce_04[0] = c;
if (c)
wsi->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;
if (c)
wsi->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;
if (c)
wsi->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;
if (c)
wsi->all_zero_nonce = 0;
wsi->lws_rx_parse_state =
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
break;
case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED:
if (wsi->all_zero_nonce && wsi->ietf_spec_revision >= 5)
wsi->rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
@ -692,6 +769,7 @@ int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c)
case 4:
case 5:
case 6:
case 7:
/*
* 04 logical framing from the spec (all this is masked when
* incoming and has to be unmasked)
@ -720,6 +798,10 @@ int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c)
* FIN. It's up to userland to buffer it up if it wants to see a
* whole unfragmented block of the original size (which may be up to
* 2^63 long!)
*
* Notice in v7 RSV4 is set to indicate 32-bit frame key is coming in
* after length, unlike extension data which is now deprecated, this
* does not impact the payload length calculation.
*/
/*
@ -751,6 +833,7 @@ 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",
@ -762,13 +845,15 @@ int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c)
case LWS_RXPS_04_FRAME_HDR_LEN:
if (c & 0x80) {
if ((c & 0x80) && wsi->ietf_spec_revision < 7) {
fprintf(stderr,
"Frame has extensions set illegally 4\n");
/* kill the connection */
return -1;
}
wsi->this_frame_masked = !!(c & 0x80);
switch (c) {
case 126:
/* control frames are not allowed to have big lengths */
@ -802,7 +887,11 @@ int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c)
break;
default:
wsi->rx_packet_length = c;
wsi->lws_rx_parse_state =
if (wsi->this_frame_masked)
wsi->lws_rx_parse_state =
LWS_RXPS_07_COLLECT_FRAME_KEY_1;
else
wsi->lws_rx_parse_state =
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
break;
}
@ -815,8 +904,12 @@ int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c)
case LWS_RXPS_04_FRAME_HDR_LEN16_1:
wsi->rx_packet_length |= c;
wsi->lws_rx_parse_state =
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
if (wsi->this_frame_masked)
wsi->lws_rx_parse_state =
LWS_RXPS_07_COLLECT_FRAME_KEY_1;
else
wsi->lws_rx_parse_state =
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
break;
case LWS_RXPS_04_FRAME_HDR_LEN64_8:
@ -871,6 +964,39 @@ int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c)
case LWS_RXPS_04_FRAME_HDR_LEN64_1:
wsi->rx_packet_length |= (size_t)c;
if (wsi->this_frame_masked)
wsi->lws_rx_parse_state =
LWS_RXPS_07_COLLECT_FRAME_KEY_1;
else
wsi->lws_rx_parse_state =
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
break;
case LWS_RXPS_07_COLLECT_FRAME_KEY_1:
wsi->frame_masking_nonce_04[0] = c;
if (c)
wsi->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;
if (c)
wsi->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;
if (c)
wsi->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;
if (c)
wsi->all_zero_nonce = 0;
wsi->lws_rx_parse_state =
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
break;

View file

@ -109,7 +109,7 @@ static inline void debug(const char *format, ...)
#define MAX_BROADCAST_PAYLOAD 2048
#define LWS_MAX_PROTOCOLS 10
#define LWS_MAX_EXTENSIONS_ACTIVE 10
#define SPEC_LATEST_SUPPORTED 6
#define SPEC_LATEST_SUPPORTED 7
#define MAX_WEBSOCKET_04_KEY_LEN 128
#define SYSTEM_RANDOM_FILEPATH "/dev/urandom"
@ -166,6 +166,11 @@ enum lws_rx_parse_state {
LWS_RXPS_04_FRAME_HDR_LEN64_2,
LWS_RXPS_04_FRAME_HDR_LEN64_1,
LWS_RXPS_07_COLLECT_FRAME_KEY_1,
LWS_RXPS_07_COLLECT_FRAME_KEY_2,
LWS_RXPS_07_COLLECT_FRAME_KEY_3,
LWS_RXPS_07_COLLECT_FRAME_KEY_4,
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED
};
@ -279,6 +284,9 @@ struct libwebsocket {
enum lws_close_status close_reason;
/* 07 specific */
char this_frame_masked;
/* client support */
char initial_handshake_hash_base64[30];
enum connection_mode mode;