mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-30 00:00:16 +01:00
implement-v76-write-and-recognize-close-req.patch
Signed-off-by: Andy Green <andy@warmcat.com>
This commit is contained in:
parent
775c0dd318
commit
4ea6006451
4 changed files with 266 additions and 66 deletions
289
libwebsockets.c
289
libwebsockets.c
|
@ -23,6 +23,30 @@ static void libwebsocket_service(struct libwebsocket *wsi, int sock);
|
||||||
#define LWS_ADDITIONAL_HDR_ALLOC 64
|
#define LWS_ADDITIONAL_HDR_ALLOC 64
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chrome (v0)
|
||||||
|
*
|
||||||
|
* GET / HTTP/1.1
|
||||||
|
* Upgrade: WebSocket
|
||||||
|
* Connection: Upgrade
|
||||||
|
* Host: 127.0.0.1:7681
|
||||||
|
* Origin: null
|
||||||
|
* Sec-WebSocket-Key1: +46 3 1 75 7Y 60
|
||||||
|
* Sec-WebSocket-Key2: m^+J358s0 6N 6e0 Q1 0 ~4~
|
||||||
|
*
|
||||||
|
* Firefox (v76)
|
||||||
|
*
|
||||||
|
* GET / HTTP/1.1
|
||||||
|
* Upgrade: WebSocket
|
||||||
|
* Host: 127.0.0.1:7681
|
||||||
|
* Connection: Upgrade
|
||||||
|
* Sec-WebSocket-Key1: EC."/$14 7 687YG+gZ 44d 16
|
||||||
|
* Origin: file://
|
||||||
|
* Sec-WebSocket-Key2: 2 / 9 0. 4 B8 77|ov968
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
enum lws_connection_states {
|
enum lws_connection_states {
|
||||||
WSI_STATE_CLOSED,
|
WSI_STATE_CLOSED,
|
||||||
WSI_STATE_HANDSHAKE_RX,
|
WSI_STATE_HANDSHAKE_RX,
|
||||||
|
@ -50,6 +74,15 @@ enum lws_token_indexes {
|
||||||
WSI_PARSING_COMPLETE
|
WSI_PARSING_COMPLETE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum lws_rx_parse_state {
|
||||||
|
LWS_RXPS_NEW,
|
||||||
|
|
||||||
|
LWS_RXPS_SEEN_76_FF,
|
||||||
|
LWS_RXPS_PULLING_76_LENGTH,
|
||||||
|
|
||||||
|
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct lws_tokens {
|
struct lws_tokens {
|
||||||
char * token;
|
char * token;
|
||||||
|
@ -64,7 +97,7 @@ struct lws_tokens {
|
||||||
|
|
||||||
struct libwebsocket {
|
struct libwebsocket {
|
||||||
int (*callback)(struct libwebsocket *,
|
int (*callback)(struct libwebsocket *,
|
||||||
enum libwebsocket_callback_reasons reason);
|
enum libwebsocket_callback_reasons reason, void *, size_t);
|
||||||
|
|
||||||
enum lws_connection_states state;
|
enum lws_connection_states state;
|
||||||
|
|
||||||
|
@ -76,6 +109,9 @@ struct libwebsocket {
|
||||||
int ietf_spec_revision;
|
int ietf_spec_revision;
|
||||||
|
|
||||||
int sock;
|
int sock;
|
||||||
|
|
||||||
|
enum lws_rx_parse_state lws_rx_parse_state;
|
||||||
|
size_t rx_packet_length;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,7 +127,8 @@ const struct lws_tokens lws_tokens[WSI_TOKEN_COUNT] = {
|
||||||
{ "\x0d\x0a", 2 },
|
{ "\x0d\x0a", 2 },
|
||||||
};
|
};
|
||||||
|
|
||||||
int libwebsocket_create_server(int port, int (*callback)(struct libwebsocket *, enum libwebsocket_callback_reasons))
|
|
||||||
|
int libwebsocket_create_server(int port, int (*callback)(struct libwebsocket *, enum libwebsocket_callback_reasons, void *, size_t))
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
int sockfd, newsockfd;
|
int sockfd, newsockfd;
|
||||||
|
@ -112,7 +149,8 @@ int libwebsocket_create_server(int port, int (*callback)(struct libwebsocket *,
|
||||||
}
|
}
|
||||||
|
|
||||||
wsi->callback = callback;
|
wsi->callback = callback;
|
||||||
wsi->ietf_spec_revision = 0;
|
// wsi->ietf_spec_revision = 0;
|
||||||
|
wsi->ietf_spec_revision = 76;
|
||||||
|
|
||||||
/* sit there listening for connects, accept and spawn session servers */
|
/* sit there listening for connects, accept and spawn session servers */
|
||||||
|
|
||||||
|
@ -187,7 +225,7 @@ void libwebsocket_close(struct libwebsocket *wsi)
|
||||||
wsi->state = WSI_STATE_DEAD_SOCKET;
|
wsi->state = WSI_STATE_DEAD_SOCKET;
|
||||||
|
|
||||||
if (wsi->callback)
|
if (wsi->callback)
|
||||||
wsi->callback(wsi, LWS_CALLBACK_CLOSED);
|
wsi->callback(wsi, LWS_CALLBACK_CLOSED, NULL, 0);
|
||||||
|
|
||||||
for (n = 0; n < WSI_TOKEN_COUNT; n++)
|
for (n = 0; n < WSI_TOKEN_COUNT; n++)
|
||||||
if (wsi->utf8_token[n].token)
|
if (wsi->utf8_token[n].token)
|
||||||
|
@ -226,13 +264,14 @@ static int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate appropriate memory */
|
/* allocate appropriate memory */
|
||||||
if (wsi->utf8_token[wsi->parser_state].token_len == wsi->current_alloc_len - 1) {
|
if (wsi->utf8_token[wsi->parser_state].token_len ==
|
||||||
|
wsi->current_alloc_len - 1) {
|
||||||
/* need to extend */
|
/* need to extend */
|
||||||
wsi->current_alloc_len += LWS_ADDITIONAL_HDR_ALLOC;
|
wsi->current_alloc_len += LWS_ADDITIONAL_HDR_ALLOC;
|
||||||
if (wsi->current_alloc_len >= LWS_MAX_HEADER_LEN) {
|
if (wsi->current_alloc_len >= LWS_MAX_HEADER_LEN) {
|
||||||
/* it's waaay to much payload, fail it */
|
/* it's waaay to much payload, fail it */
|
||||||
strcpy(wsi->utf8_token[wsi->parser_state].token,
|
strcpy(wsi->utf8_token[wsi->parser_state].token,
|
||||||
"!!! Length exceeded maximum supported !!!");
|
"!!! Length exceeded maximum supported !!!");
|
||||||
wsi->parser_state = WSI_TOKEN_SKIPPING;
|
wsi->parser_state = WSI_TOKEN_SKIPPING;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -349,6 +388,76 @@ static int interpret_key(const char *key, unsigned int *result)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
unsigned char buf[2];
|
||||||
|
|
||||||
|
switch (wsi->lws_rx_parse_state) {
|
||||||
|
case LWS_RXPS_NEW:
|
||||||
|
|
||||||
|
switch (wsi->ietf_spec_revision) {
|
||||||
|
/* Firefox 4.0b6 likes this as of 30 Oct */
|
||||||
|
case 76:
|
||||||
|
if (c == 0xff)
|
||||||
|
wsi->lws_rx_parse_state = LWS_RXPS_SEEN_76_FF;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LWS_RXPS_SEEN_76_FF:
|
||||||
|
if (c != 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Seen that client is requesting a v76 close, sending ack\n");
|
||||||
|
buf[0] = 0xff;
|
||||||
|
buf[1] = 0;
|
||||||
|
n = write(wsi->sock, buf, 2);
|
||||||
|
if (n < 0) {
|
||||||
|
fprintf(stderr, "ERROR writing to socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fprintf(stderr, " v76 close ack sent, server closing socket\n");
|
||||||
|
/* returning < 0 will get it closed in parent */
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
case LWS_RXPS_PULLING_76_LENGTH:
|
||||||
|
break;
|
||||||
|
case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int libwebsocket_interpret_incoming_packet(struct libwebsocket *wsi,
|
||||||
|
unsigned char *buf, size_t len)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
fprintf(stderr, "received %d byte packet\n", (int)len);
|
||||||
|
for (n = 0; n < len; n++)
|
||||||
|
fprintf(stderr, "%02X ", buf[n]);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
|
/* let the rx protocol state machine have as much as it needs */
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
while (wsi->lws_rx_parse_state !=
|
||||||
|
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED && n < len)
|
||||||
|
if (libwebsocket_rx_sm(wsi, buf[n++]) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (n != len) {
|
||||||
|
if (wsi->callback)
|
||||||
|
wsi->callback(wsi, LWS_CALLBACK_RECEIVE, &buf[n], len - n);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have to take care about parsing because the headers may be split
|
* We have to take care about parsing because the headers may be split
|
||||||
|
@ -372,8 +481,7 @@ int libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len)
|
||||||
/* fallthru */
|
/* fallthru */
|
||||||
case WSI_STATE_HANDSHAKE_RX:
|
case WSI_STATE_HANDSHAKE_RX:
|
||||||
|
|
||||||
fprintf(stderr, "issuing %ld bytes to parser\n", len);
|
fprintf(stderr, "issuing %d bytes to parser\n", (int)len);
|
||||||
|
|
||||||
|
|
||||||
fwrite(buf, 1, len, stderr);
|
fwrite(buf, 1, len, stderr);
|
||||||
for (n = 0; n< len; n++)
|
for (n = 0; n< len; n++)
|
||||||
|
@ -402,6 +510,8 @@ int libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len)
|
||||||
|
|
||||||
/* create the response packet */
|
/* create the response packet */
|
||||||
|
|
||||||
|
/* make a buffer big enough for everything */
|
||||||
|
|
||||||
response = malloc(256 +
|
response = malloc(256 +
|
||||||
wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len +
|
wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len +
|
||||||
wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len +
|
wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len +
|
||||||
|
@ -409,13 +519,16 @@ int libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len)
|
||||||
wsi->utf8_token[WSI_TOKEN_ORIGIN].token_len +
|
wsi->utf8_token[WSI_TOKEN_ORIGIN].token_len +
|
||||||
wsi->utf8_token[WSI_TOKEN_GET_URI].token_len +
|
wsi->utf8_token[WSI_TOKEN_GET_URI].token_len +
|
||||||
wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len);
|
wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len);
|
||||||
|
if (!response) {
|
||||||
|
fprintf(stderr, "Out of memory for response buffer\n");
|
||||||
fprintf(stderr, "'%s;\n", wsi->utf8_token[WSI_TOKEN_HOST].token);
|
goto bail;
|
||||||
|
}
|
||||||
|
|
||||||
p = response;
|
p = response;
|
||||||
strcpy(p, "HTTP/1.1 101 WebSocket Protocol Handshake\x0d\x0aUpgrade: WebSocket\x0d\x0a");
|
strcpy(p, "HTTP/1.1 101 WebSocket Protocol Handshake\x0d\x0a"
|
||||||
p += strlen("HTTP/1.1 101 WebSocket Protocol Handshake\x0d\x0aUpgrade: WebSocket\x0d\x0a");
|
"Upgrade: WebSocket\x0d\x0a");
|
||||||
|
p += strlen("HTTP/1.1 101 WebSocket Protocol Handshake\x0d\x0a"
|
||||||
|
"Upgrade: WebSocket\x0d\x0a");
|
||||||
strcpy(p, "Connection: Upgrade\x0d\x0aSec-WebSocket-Origin: ");
|
strcpy(p, "Connection: Upgrade\x0d\x0aSec-WebSocket-Origin: ");
|
||||||
p += strlen("Connection: Upgrade\x0d\x0aSec-WebSocket-Origin: ");
|
p += strlen("Connection: Upgrade\x0d\x0aSec-WebSocket-Origin: ");
|
||||||
strcpy(p, wsi->utf8_token[WSI_TOKEN_ORIGIN].token);
|
strcpy(p, wsi->utf8_token[WSI_TOKEN_ORIGIN].token);
|
||||||
|
@ -442,7 +555,6 @@ int libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len)
|
||||||
|
|
||||||
if (interpret_key(wsi->utf8_token[WSI_TOKEN_KEY1].token, &key1))
|
if (interpret_key(wsi->utf8_token[WSI_TOKEN_KEY1].token, &key1))
|
||||||
goto bail;
|
goto bail;
|
||||||
|
|
||||||
if (interpret_key(wsi->utf8_token[WSI_TOKEN_KEY2].token, &key2))
|
if (interpret_key(wsi->utf8_token[WSI_TOKEN_KEY2].token, &key2))
|
||||||
goto bail;
|
goto bail;
|
||||||
|
|
||||||
|
@ -469,10 +581,10 @@ int libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len)
|
||||||
md5(sum, 16, (unsigned char *)p);
|
md5(sum, 16, (unsigned char *)p);
|
||||||
p += 16;
|
p += 16;
|
||||||
|
|
||||||
/* it's complete, go ahead and send it */
|
/* it's complete: go ahead and send it */
|
||||||
|
|
||||||
fprintf(stderr, "issuing response packet %d len\n",
|
fprintf(stderr, "issuing response packet %d len\n",
|
||||||
(int)(p - response));
|
(int)(p - response));
|
||||||
fwrite(response, 1, p - response, stderr);
|
fwrite(response, 1, p - response, stderr);
|
||||||
|
|
||||||
n = write(wsi->sock, response, p - response);
|
n = write(wsi->sock, response, p - response);
|
||||||
|
@ -480,18 +592,22 @@ int libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len)
|
||||||
fprintf(stderr, "ERROR writing to socket");
|
fprintf(stderr, "ERROR writing to socket");
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* alright clean up and set ourselves into established state */
|
||||||
|
|
||||||
free(response);
|
free(response);
|
||||||
wsi->state = WSI_STATE_ESTABLISHED;
|
wsi->state = WSI_STATE_ESTABLISHED;
|
||||||
|
wsi->lws_rx_parse_state = LWS_RXPS_NEW;
|
||||||
|
|
||||||
/* notify user code that we're ready to roll */
|
/* notify user code that we're ready to roll */
|
||||||
|
|
||||||
if (wsi->callback)
|
if (wsi->callback)
|
||||||
wsi->callback(wsi, LWS_CALLBACK_ESTABLISHED);
|
wsi->callback(wsi, LWS_CALLBACK_ESTABLISHED, NULL, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WSI_STATE_ESTABLISHED:
|
case WSI_STATE_ESTABLISHED:
|
||||||
fprintf(stderr, "received %ld byte packet\n", len);
|
if (libwebsocket_interpret_incoming_packet(wsi, buf, len) < 0)
|
||||||
|
goto bail;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -504,68 +620,127 @@ bail:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int libwebsocket_write(struct libwebsocket * wsi, void *buf, size_t len)
|
|
||||||
|
/*
|
||||||
|
* notice, we will use up to LWS_SEND_BUFFER_PRE_PADDING bytes BEFORE the
|
||||||
|
* buffer pointer given and LWS_SEND_BUFFER_POST_PADDING bytes AFTER
|
||||||
|
* buf + len !!! Caller must allocate and offset pointer accordingly!
|
||||||
|
*
|
||||||
|
* This lets us send packets in one write() action including the protocol
|
||||||
|
* pre- and post- data without copying the payload around.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int libwebsocket_write(struct libwebsocket * wsi, unsigned char *buf,
|
||||||
|
size_t len, int is_binary)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
unsigned char hdr[9];
|
int pre = 0;
|
||||||
|
int post = 0;
|
||||||
|
unsigned int shift = 7;
|
||||||
|
|
||||||
if (wsi->state != WSI_STATE_ESTABLISHED)
|
if (wsi->state != WSI_STATE_ESTABLISHED)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
switch (wsi->ietf_spec_revision) {
|
switch (wsi->ietf_spec_revision) {
|
||||||
/* chrome */
|
/* Firefox 4.0b6 likes this as of 30 Oct */
|
||||||
case 0:
|
case 76:
|
||||||
hdr[0] = 0xff;
|
if (is_binary) {
|
||||||
hdr[1] = len >> 56;
|
/* in binary mode we send 7-bit used length blocks */
|
||||||
hdr[2] = len >> 48;
|
pre = 1;
|
||||||
hdr[3] = len >> 40;
|
while (len & (127 << shift)) {
|
||||||
hdr[4] = len >> 32;
|
pre++;
|
||||||
hdr[5] = len >> 24;
|
shift += 7;
|
||||||
hdr[6] = len >> 16;
|
}
|
||||||
hdr[7] = len >> 8;
|
n = 0;
|
||||||
hdr[8] = len;
|
shift -= 7;
|
||||||
|
while (shift >= 0) {
|
||||||
n = write(wsi->sock, hdr, sizeof hdr);
|
if (shift)
|
||||||
if (n < 0) {
|
buf[0 - pre + n] =
|
||||||
fprintf(stderr, "ERROR writing to socket");
|
((len >> shift) & 127) | 0x80;
|
||||||
return -1;
|
else
|
||||||
|
buf[0 - pre + n] =
|
||||||
|
((len >> shift) & 127);
|
||||||
|
n++;
|
||||||
|
shift -= 7;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* frame type = text, length-free spam mode */
|
||||||
|
|
||||||
|
buf[-1] = 0;
|
||||||
|
buf[len] = 0xff; /* EOT marker */
|
||||||
|
pre = 1;
|
||||||
|
post = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* chrome likes this as of 30 Oct */
|
||||||
|
case 0:
|
||||||
|
buf[-9] = 0xff;
|
||||||
|
#if defined __LP64__
|
||||||
|
buf[-8] = len >> 56;
|
||||||
|
buf[-7] = len >> 48;
|
||||||
|
buf[-6] = len >> 40;
|
||||||
|
buf[-5] = len >> 32;
|
||||||
|
#else
|
||||||
|
buf[-8] = 0;
|
||||||
|
buf[-7] = 0;
|
||||||
|
buf[-6] = 0;
|
||||||
|
buf[-5] = 0;
|
||||||
|
#endif
|
||||||
|
buf[-4] = len >> 24;
|
||||||
|
buf[-3] = len >> 16;
|
||||||
|
buf[-2] = len >> 8;
|
||||||
|
buf[-1] = len;
|
||||||
|
pre = 9;
|
||||||
|
break;
|
||||||
|
|
||||||
/* just an unimplemented spec right now apparently */
|
/* just an unimplemented spec right now apparently */
|
||||||
case 2:
|
case 2:
|
||||||
n = 0;
|
n = 4; /* text */
|
||||||
|
if (is_binary)
|
||||||
|
n = 5; /* binary */
|
||||||
if (len < 126) {
|
if (len < 126) {
|
||||||
hdr[n++] = 0x04;
|
buf[-2] = n;
|
||||||
hdr[n++] = len;
|
buf[-1] = len;
|
||||||
|
pre = 2;
|
||||||
} else {
|
} else {
|
||||||
if (len < 65536) {
|
if (len < 65536) {
|
||||||
hdr[n++] = 0x04; /* text frame */
|
buf[-4] = n;
|
||||||
hdr[n++] = 126;
|
buf[-3] = 126;
|
||||||
hdr[n++] = len >> 8;
|
buf[-2] = len >> 8;
|
||||||
hdr[n++] = len;
|
buf[-1] = len;
|
||||||
|
pre = 4;
|
||||||
} else {
|
} else {
|
||||||
hdr[n++] = 0x04;
|
buf[-10] = n;
|
||||||
hdr[n++] = 127;
|
buf[-9] = 127;
|
||||||
hdr[n++] = len >> 24;
|
#if defined __LP64__
|
||||||
hdr[n++] = len >> 16;
|
buf[-8] = (len >> 56) & 0x7f;
|
||||||
hdr[n++] = len >> 8;
|
buf[-7] = len >> 48;
|
||||||
hdr[n++] = len;
|
buf[-6] = len >> 40;
|
||||||
|
buf[-5] = len >> 32;
|
||||||
|
#else
|
||||||
|
buf[-8] = 0;
|
||||||
|
buf[-7] = 0;
|
||||||
|
buf[-6] = 0;
|
||||||
|
buf[-5] = 0;
|
||||||
|
#endif
|
||||||
|
buf[-4] = len >> 24;
|
||||||
|
buf[-3] = len >> 16;
|
||||||
|
buf[-2] = len >> 8;
|
||||||
|
buf[-1] = len;
|
||||||
|
pre = 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
n = write(wsi->sock, hdr, n);
|
|
||||||
if (n < 0) {
|
|
||||||
fprintf(stderr, "ERROR writing to socket");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
n = write(wsi->sock, buf, len);
|
n = write(wsi->sock, buf - pre, len + pre + post);
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
fprintf(stderr, "ERROR writing to socket");
|
fprintf(stderr, "ERROR writing to socket");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "written %d bytes to websocket\n", (int)len);
|
fprintf(stderr, "written %d bytes to websocket\n", (int)len);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -616,7 +791,7 @@ static void libwebsocket_service(struct libwebsocket *wsi, int sock)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (wsi->callback)
|
if (wsi->callback)
|
||||||
wsi->callback(wsi, LWS_CALLBACK_SEND);
|
wsi->callback(wsi, LWS_CALLBACK_SEND, NULL, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,30 @@ struct libwebsocket;
|
||||||
|
|
||||||
extern int libwebsocket_create_server(int port,
|
extern int libwebsocket_create_server(int port,
|
||||||
int (*callback)(struct libwebsocket *,
|
int (*callback)(struct libwebsocket *,
|
||||||
enum libwebsocket_callback_reasons));
|
enum libwebsocket_callback_reasons, void *, size_t));
|
||||||
|
|
||||||
extern int libwebsocket_write(struct libwebsocket *, void *buf, size_t len);
|
/*
|
||||||
|
* IMPORTANT NOTICE!
|
||||||
|
*
|
||||||
|
* The send buffer has to have LWS_SEND_BUFFER_PRE_PADDING bytes valid BEFORE
|
||||||
|
* buf, and LWS_SEND_BUFFER_POST_PADDING bytes valid AFTER (buf + len).
|
||||||
|
*
|
||||||
|
* This allows us to add protocol info before and after the data, and send as
|
||||||
|
* one packet on the network without payload copying, for maximum efficiency.
|
||||||
|
*
|
||||||
|
* So for example you need this kind of code to use libwebsocket_write with a
|
||||||
|
* 128-byte payload
|
||||||
|
*
|
||||||
|
* char buf[LWS_SEND_BUFFER_PRE_PADDING + 128 + LWS_SEND_BUFFER_POST_PADDING];
|
||||||
|
*
|
||||||
|
* // fill your part of the buffer... for example here it's all zeros
|
||||||
|
* memset(&buf[LWS_SEND_BUFFER_PRE_PADDING], 0, 128);
|
||||||
|
*
|
||||||
|
* libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], 128);
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LWS_SEND_BUFFER_PRE_PADDING 12
|
||||||
|
#define LWS_SEND_BUFFER_POST_PADDING 1
|
||||||
|
|
||||||
|
extern int libwebsocket_write(struct libwebsocket *, unsigned char *buf, size_t len, int is_binary);
|
||||||
|
|
|
@ -6,11 +6,11 @@
|
||||||
|
|
||||||
#define PORT 7681
|
#define PORT 7681
|
||||||
|
|
||||||
int websocket_callback(struct libwebsocket * wsi,
|
static int websocket_callback(struct libwebsocket * wsi,
|
||||||
enum libwebsocket_callback_reasons reason)
|
enum libwebsocket_callback_reasons reason, void *in, size_t len)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
char buf[256];
|
char buf[LWS_SEND_BUFFER_PRE_PADDING + 256 + LWS_SEND_BUFFER_POST_PADDING];
|
||||||
static int bump;
|
static int bump;
|
||||||
|
|
||||||
switch (reason) {
|
switch (reason) {
|
||||||
|
@ -24,8 +24,8 @@ int websocket_callback(struct libwebsocket * wsi,
|
||||||
|
|
||||||
case LWS_CALLBACK_SEND:
|
case LWS_CALLBACK_SEND:
|
||||||
sleep(1);
|
sleep(1);
|
||||||
n = sprintf(buf, "%d\n", bump++);
|
n = sprintf(&buf[LWS_SEND_BUFFER_PRE_PADDING], "%d\n", bump++);
|
||||||
n = libwebsocket_write(wsi, buf, n);
|
n = libwebsocket_write(wsi, (unsigned char *)&buf[LWS_SEND_BUFFER_PRE_PADDING], n, 0);
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
fprintf(stderr, "ERROR writing to socket");
|
fprintf(stderr, "ERROR writing to socket");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -33,6 +33,7 @@ int websocket_callback(struct libwebsocket * wsi,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LWS_CALLBACK_RECEIVE:
|
case LWS_CALLBACK_RECEIVE:
|
||||||
|
fprintf(stderr, "Received %d bytes payload\n", (int)len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
// alert('<p class="event">Socket Status: '+socket.readyState);
|
// alert('<p class="event">Socket Status: '+socket.readyState);
|
||||||
|
|
||||||
socket.onopen = function(){
|
socket.onopen = function(){
|
||||||
alert('<p class="event">Socket Status: '+socket.readyState+' (open)');
|
// alert('<p class="event">Socket Status: '+socket.readyState+' (open)');
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.onmessage = got_packet;
|
socket.onmessage = got_packet;
|
||||||
|
@ -28,8 +28,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function got_packet(msg){
|
function got_packet(msg){
|
||||||
// alert('got packet' + msg);
|
|
||||||
|
|
||||||
|
// alert('got packet' + msg.data);
|
||||||
document.write(msg.data + "\n");
|
document.write(msg.data + "\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue