test-case-for-mozilla-issue
This commit is contained in:
parent
ff95d7a50c
commit
775c0dd318
5 changed files with 339 additions and 127 deletions
12
Makefile
12
Makefile
|
@ -1,8 +1,14 @@
|
|||
CFLAGS= -Wall -Werror -rdynamic -fPIC -c
|
||||
|
||||
all:
|
||||
gcc -Wall -Werror -rdynamic -fPIC -c libwebsockets.c
|
||||
gcc -Wall -Werror -rdynamic -fPIC -c md5.c
|
||||
gcc $(CFLAGS) libwebsockets.c
|
||||
gcc $(CFLAGS) md5.c
|
||||
gcc libwebsockets.o md5.o --shared -o libwebsockets.so
|
||||
|
||||
gcc $(CFLAGS) test-server.c
|
||||
gcc test-server.o ./libwebsockets.so -o test-server
|
||||
|
||||
clean:
|
||||
rm -f *.o *.so
|
||||
rm -f *.o *.so test-server
|
||||
|
||||
|
||||
|
|
287
libwebsockets.c
287
libwebsockets.c
|
@ -3,6 +3,7 @@
|
|||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
@ -14,8 +15,69 @@
|
|||
#include "libwebsockets.h"
|
||||
|
||||
void md5(const unsigned char *input, int ilen, unsigned char output[16]);
|
||||
static void libwebsocket_service(struct libwebsocket *wsi, int sock);
|
||||
|
||||
#define LWS_MAX_HEADER_NAME_LENGTH 64
|
||||
#define LWS_MAX_HEADER_LEN 4096
|
||||
#define LWS_INITIAL_HDR_ALLOC 256
|
||||
#define LWS_ADDITIONAL_HDR_ALLOC 64
|
||||
|
||||
|
||||
enum lws_connection_states {
|
||||
WSI_STATE_CLOSED,
|
||||
WSI_STATE_HANDSHAKE_RX,
|
||||
WSI_STATE_DEAD_SOCKET,
|
||||
WSI_STATE_ESTABLISHED
|
||||
};
|
||||
|
||||
enum lws_token_indexes {
|
||||
WSI_TOKEN_GET_URI,
|
||||
WSI_TOKEN_HOST,
|
||||
WSI_TOKEN_CONNECTION,
|
||||
WSI_TOKEN_KEY1,
|
||||
WSI_TOKEN_KEY2,
|
||||
WSI_TOKEN_PROTOCOL,
|
||||
WSI_TOKEN_UPGRADE,
|
||||
WSI_TOKEN_ORIGIN,
|
||||
WSI_TOKEN_CHALLENGE,
|
||||
|
||||
/* always last real token index*/
|
||||
WSI_TOKEN_COUNT,
|
||||
/* parser state additions */
|
||||
WSI_TOKEN_NAME_PART,
|
||||
WSI_TOKEN_SKIPPING,
|
||||
WSI_TOKEN_SKIPPING_SAW_CR,
|
||||
WSI_PARSING_COMPLETE
|
||||
};
|
||||
|
||||
|
||||
struct lws_tokens {
|
||||
char * token;
|
||||
int token_len;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* This is totally opaque to code using the library. It's exported as a
|
||||
* forward-reference pointer-only declaration.
|
||||
*/
|
||||
|
||||
struct libwebsocket {
|
||||
int (*callback)(struct libwebsocket *,
|
||||
enum libwebsocket_callback_reasons reason);
|
||||
|
||||
enum lws_connection_states state;
|
||||
|
||||
char name_buffer[LWS_MAX_HEADER_NAME_LENGTH];
|
||||
int name_buffer_pos;
|
||||
int current_alloc_len;
|
||||
enum lws_token_indexes parser_state;
|
||||
struct lws_tokens utf8_token[WSI_TOKEN_COUNT];
|
||||
int ietf_spec_revision;
|
||||
|
||||
int sock;
|
||||
};
|
||||
|
||||
void dostuff(struct libwebsocket *wsi, int sock);
|
||||
|
||||
const struct lws_tokens lws_tokens[WSI_TOKEN_COUNT] = {
|
||||
{ "GET ", 4 },
|
||||
|
@ -29,24 +91,47 @@ const struct lws_tokens lws_tokens[WSI_TOKEN_COUNT] = {
|
|||
{ "\x0d\x0a", 2 },
|
||||
};
|
||||
|
||||
int libwebsocket_init(struct libwebsocket *wsi, int port)
|
||||
int libwebsocket_create_server(int port, int (*callback)(struct libwebsocket *, enum libwebsocket_callback_reasons))
|
||||
{
|
||||
int n;
|
||||
int sockfd, newsockfd;
|
||||
unsigned int clilen;
|
||||
struct sockaddr_in serv_addr, cli_addr;
|
||||
int pid;
|
||||
struct libwebsocket *wsi = malloc(sizeof(struct libwebsocket));
|
||||
|
||||
if (!wsi)
|
||||
return -1;
|
||||
|
||||
wsi->state = WSI_STATE_CLOSED;
|
||||
wsi->name_buffer_pos = 0;
|
||||
wsi->response = NULL;
|
||||
|
||||
for (n = 0; n < WSI_TOKEN_COUNT; n++) {
|
||||
wsi->utf8_token[n].token = NULL;
|
||||
wsi->utf8_token[n].token_len = 0;
|
||||
}
|
||||
|
||||
wsi->callback = callback;
|
||||
wsi->ietf_spec_revision = 0;
|
||||
|
||||
/* fork off a master server for this websocket server */
|
||||
/* sit there listening for connects, accept and spawn session servers */
|
||||
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sockfd < 0) {
|
||||
fprintf(stderr, "ERROR opening socket");
|
||||
}
|
||||
bzero((char *) &serv_addr, sizeof(serv_addr));
|
||||
|
||||
serv_addr.sin_family = AF_INET;
|
||||
serv_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
serv_addr.sin_port = htons(port);
|
||||
n = bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
|
||||
if (n < 0) {
|
||||
fprintf(stderr, "ERROR on binding %d %d\n", n, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* fork off a master server for this websocket server */
|
||||
|
||||
n = fork();
|
||||
if (n < 0) {
|
||||
|
@ -59,18 +144,6 @@ int libwebsocket_init(struct libwebsocket *wsi, int port)
|
|||
if (n)
|
||||
return 0;
|
||||
|
||||
/* sit there listening for connects, accept and spawn session servers */
|
||||
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sockfd < 0)
|
||||
fprintf(stderr, "ERROR opening socket");
|
||||
bzero((char *) &serv_addr, sizeof(serv_addr));
|
||||
|
||||
serv_addr.sin_family = AF_INET;
|
||||
serv_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
serv_addr.sin_port = htons(port);
|
||||
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
|
||||
fprintf(stderr, "ERROR on binding");
|
||||
|
||||
listen(sockfd, 5);
|
||||
|
||||
|
@ -78,23 +151,32 @@ int libwebsocket_init(struct libwebsocket *wsi, int port)
|
|||
clilen = sizeof(cli_addr);
|
||||
|
||||
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
|
||||
if (newsockfd < 0)
|
||||
if (newsockfd < 0) {
|
||||
fprintf(stderr, "ERROR on accept");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* fork off a new server instance */
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0)
|
||||
if (pid < 0) {
|
||||
fprintf(stderr, "ERROR on fork");
|
||||
if (!pid) {
|
||||
close(sockfd);
|
||||
|
||||
/* sit in dostuff() until session socket closed */
|
||||
|
||||
dostuff(wsi, newsockfd);
|
||||
exit(0);
|
||||
} else
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pid) {
|
||||
close(newsockfd);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* we are the session process */
|
||||
|
||||
close(sockfd);
|
||||
|
||||
/* sit in libwebsocket_service() until session socket closed */
|
||||
|
||||
libwebsocket_service(wsi, newsockfd);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,15 +186,12 @@ void libwebsocket_close(struct libwebsocket *wsi)
|
|||
|
||||
wsi->state = WSI_STATE_DEAD_SOCKET;
|
||||
|
||||
if (wsi->websocket_closed_callback)
|
||||
wsi->websocket_closed_callback(wsi);
|
||||
if (wsi->callback)
|
||||
wsi->callback(wsi, LWS_CALLBACK_CLOSED);
|
||||
|
||||
for (n = 0; n < WSI_TOKEN_COUNT; n++)
|
||||
if (wsi->utf8_token[n].token)
|
||||
free(wsi->utf8_token[n].token);
|
||||
|
||||
if (wsi->response)
|
||||
free(wsi->response);
|
||||
}
|
||||
|
||||
|
||||
|
@ -174,12 +253,12 @@ static int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c)
|
|||
wsi->utf8_token[wsi->parser_state].token_len++] = c;
|
||||
|
||||
/* special payload limiting */
|
||||
if (wsi->parser_state == WSI_TOKEN_CHALLENGE)
|
||||
if (wsi->utf8_token[wsi->parser_state].token_len == 8) {
|
||||
// fprintf(stderr, "Setting WSI_PARSING_COMPLETE\n");
|
||||
wsi->parser_state = WSI_PARSING_COMPLETE;
|
||||
break;
|
||||
}
|
||||
if (wsi->parser_state == WSI_TOKEN_CHALLENGE &&
|
||||
wsi->utf8_token[wsi->parser_state].token_len == 8) {
|
||||
// fprintf(stderr, "Setting WSI_PARSING_COMPLETE\n");
|
||||
wsi->parser_state = WSI_PARSING_COMPLETE;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
@ -274,7 +353,8 @@ static int interpret_key(const char *key, unsigned int *result)
|
|||
/*
|
||||
* We have to take care about parsing because the headers may be split
|
||||
* into multiple fragments. They may contain unknown headers with arbitrary
|
||||
* argument lengths.
|
||||
* argument lengths. So, we parse using a single-character at a time state
|
||||
* machine that is completely independent of packet size.
|
||||
*/
|
||||
|
||||
int libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len)
|
||||
|
@ -283,11 +363,13 @@ int libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len)
|
|||
char *p;
|
||||
unsigned int key1, key2;
|
||||
unsigned char sum[16];
|
||||
char *response;
|
||||
|
||||
switch (wsi->state) {
|
||||
case WSI_STATE_CLOSED:
|
||||
wsi->state = WSI_STATE_HANDSHAKE_RX;
|
||||
wsi->parser_state = WSI_TOKEN_NAME_PART;
|
||||
/* fallthru */
|
||||
case WSI_STATE_HANDSHAKE_RX:
|
||||
|
||||
fprintf(stderr, "issuing %ld bytes to parser\n", len);
|
||||
|
@ -320,7 +402,7 @@ int libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len)
|
|||
|
||||
/* create the response packet */
|
||||
|
||||
wsi->response = malloc(256 +
|
||||
response = malloc(256 +
|
||||
wsi->utf8_token[WSI_TOKEN_UPGRADE].token_len +
|
||||
wsi->utf8_token[WSI_TOKEN_CONNECTION].token_len +
|
||||
wsi->utf8_token[WSI_TOKEN_HOST].token_len +
|
||||
|
@ -331,7 +413,7 @@ int libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len)
|
|||
|
||||
fprintf(stderr, "'%s;\n", wsi->utf8_token[WSI_TOKEN_HOST].token);
|
||||
|
||||
p = wsi->response;
|
||||
p = response;
|
||||
strcpy(p, "HTTP/1.1 101 WebSocket Protocol Handshake\x0d\x0aUpgrade: WebSocket\x0d\x0a");
|
||||
p += strlen("HTTP/1.1 101 WebSocket Protocol Handshake\x0d\x0aUpgrade: WebSocket\x0d\x0a");
|
||||
strcpy(p, "Connection: Upgrade\x0d\x0aSec-WebSocket-Origin: ");
|
||||
|
@ -349,15 +431,22 @@ int libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len)
|
|||
if (wsi->utf8_token[WSI_TOKEN_PROTOCOL].token) {
|
||||
strcpy(p, wsi->utf8_token[WSI_TOKEN_PROTOCOL].token);
|
||||
p += wsi->utf8_token[WSI_TOKEN_PROTOCOL].token_len;
|
||||
} else {
|
||||
strcpy(p, "none");
|
||||
p += strlen("none");
|
||||
}
|
||||
strcpy(p, "\x0d\x0a\x0d\x0a");
|
||||
p += strlen("\x0d\x0a\x0d\x0a");
|
||||
|
||||
/* convert the two keys into 32-bit integers */
|
||||
|
||||
if (interpret_key(wsi->utf8_token[WSI_TOKEN_KEY1].token, &key1))
|
||||
goto bail;
|
||||
|
||||
if (interpret_key(wsi->utf8_token[WSI_TOKEN_KEY2].token, &key2))
|
||||
goto bail;
|
||||
|
||||
/* lay them out in network byte order (MSB first */
|
||||
|
||||
sum[0] = key1 >> 24;
|
||||
sum[1] = key1 >> 16;
|
||||
|
@ -367,20 +456,42 @@ int libwebsocket_read(struct libwebsocket *wsi, unsigned char * buf, size_t len)
|
|||
sum[5] = key2 >> 16;
|
||||
sum[6] = key2 >> 8;
|
||||
sum[7] = key2;
|
||||
|
||||
/* follow them with the challenge token we were sent */
|
||||
|
||||
memcpy(&sum[8], wsi->utf8_token[WSI_TOKEN_CHALLENGE].token, 8);
|
||||
|
||||
/*
|
||||
* compute the md5sum of that 16-byte series and use as our
|
||||
* payload after our headers
|
||||
*/
|
||||
|
||||
md5(sum, 16, (unsigned char *)p);
|
||||
p += 16;
|
||||
|
||||
wsi->response_length = p - wsi->response;
|
||||
|
||||
wsi->state = WSI_STATE_ISSUE_HANDSHAKE;
|
||||
/* it's complete, go ahead and send it */
|
||||
|
||||
if (wsi->websocket_established_callback)
|
||||
wsi->websocket_established_callback(wsi);
|
||||
fprintf(stderr, "issuing response packet %d len\n",
|
||||
(int)(p - response));
|
||||
fwrite(response, 1, p - response, stderr);
|
||||
|
||||
n = write(wsi->sock, response, p - response);
|
||||
if (n < 0) {
|
||||
fprintf(stderr, "ERROR writing to socket");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
free(response);
|
||||
wsi->state = WSI_STATE_ESTABLISHED;
|
||||
|
||||
/* notify user code that we're ready to roll */
|
||||
|
||||
if (wsi->callback)
|
||||
wsi->callback(wsi, LWS_CALLBACK_ESTABLISHED);
|
||||
break;
|
||||
|
||||
case WSI_STATE_ESTABLISHED:
|
||||
fprintf(stderr, "received %ld byte packet\n", len);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -393,8 +504,74 @@ bail:
|
|||
return -1;
|
||||
}
|
||||
|
||||
int libwebsocket_write(struct libwebsocket * wsi, void *buf, size_t len)
|
||||
{
|
||||
int n;
|
||||
unsigned char hdr[9];
|
||||
|
||||
if (wsi->state != WSI_STATE_ESTABLISHED)
|
||||
return -1;
|
||||
|
||||
void dostuff(struct libwebsocket *wsi, int sock)
|
||||
switch (wsi->ietf_spec_revision) {
|
||||
/* chrome */
|
||||
case 0:
|
||||
hdr[0] = 0xff;
|
||||
hdr[1] = len >> 56;
|
||||
hdr[2] = len >> 48;
|
||||
hdr[3] = len >> 40;
|
||||
hdr[4] = len >> 32;
|
||||
hdr[5] = len >> 24;
|
||||
hdr[6] = len >> 16;
|
||||
hdr[7] = len >> 8;
|
||||
hdr[8] = len;
|
||||
|
||||
n = write(wsi->sock, hdr, sizeof hdr);
|
||||
if (n < 0) {
|
||||
fprintf(stderr, "ERROR writing to socket");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
/* just an unimplemented spec right now apparently */
|
||||
case 2:
|
||||
n = 0;
|
||||
if (len < 126) {
|
||||
hdr[n++] = 0x04;
|
||||
hdr[n++] = len;
|
||||
} else {
|
||||
if (len < 65536) {
|
||||
hdr[n++] = 0x04; /* text frame */
|
||||
hdr[n++] = 126;
|
||||
hdr[n++] = len >> 8;
|
||||
hdr[n++] = len;
|
||||
} else {
|
||||
hdr[n++] = 0x04;
|
||||
hdr[n++] = 127;
|
||||
hdr[n++] = len >> 24;
|
||||
hdr[n++] = len >> 16;
|
||||
hdr[n++] = len >> 8;
|
||||
hdr[n++] = len;
|
||||
}
|
||||
}
|
||||
n = write(wsi->sock, hdr, n);
|
||||
if (n < 0) {
|
||||
fprintf(stderr, "ERROR writing to socket");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
n = write(wsi->sock, buf, len);
|
||||
if (n < 0) {
|
||||
fprintf(stderr, "ERROR writing to socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(stderr, "written %d bytes to websocket\n", (int)len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void libwebsocket_service(struct libwebsocket *wsi, int sock)
|
||||
{
|
||||
int n;
|
||||
unsigned char buf[256];
|
||||
|
@ -435,23 +612,11 @@ void dostuff(struct libwebsocket *wsi, int sock)
|
|||
libwebsocket_read(wsi, buf, n);
|
||||
}
|
||||
|
||||
if (wsi->state == WSI_STATE_ISSUE_HANDSHAKE) {
|
||||
|
||||
fprintf(stderr, "issuing response packet %d len\n", wsi->response_length);
|
||||
|
||||
fwrite(wsi->response, 1, wsi->response_length, stderr);
|
||||
|
||||
n = write(sock, wsi->response, wsi->response_length);
|
||||
if (n < 0) {
|
||||
fprintf(stderr, "ERROR writing to socket");
|
||||
exit(1);
|
||||
}
|
||||
wsi->state = WSI_STATE_ESTABLISHED;
|
||||
if (wsi->state != WSI_STATE_ESTABLISHED)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (wsi->websocket_send_callback)
|
||||
wsi->websocket_send_callback(wsi);
|
||||
if (wsi->callback)
|
||||
wsi->callback(wsi, LWS_CALLBACK_SEND);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,68 +1,15 @@
|
|||
|
||||
#define LWS_MAX_HEADER_NAME_LENGTH 64
|
||||
#define LWS_MAX_HEADER_LEN 4096
|
||||
#define LWS_INITIAL_HDR_ALLOC 256
|
||||
#define LWS_ADDITIONAL_HDR_ALLOC 64
|
||||
|
||||
|
||||
enum lws_connection_states {
|
||||
WSI_STATE_CLOSED,
|
||||
WSI_STATE_HANDSHAKE_RX,
|
||||
WSI_STATE_ISSUE_HANDSHAKE,
|
||||
WSI_STATE_DEAD_SOCKET,
|
||||
WSI_STATE_ESTABLISHED
|
||||
enum libwebsocket_callback_reasons {
|
||||
LWS_CALLBACK_ESTABLISHED,
|
||||
LWS_CALLBACK_CLOSED,
|
||||
LWS_CALLBACK_SEND,
|
||||
LWS_CALLBACK_RECEIVE,
|
||||
};
|
||||
|
||||
enum lws_token_indexes {
|
||||
WSI_TOKEN_GET_URI,
|
||||
WSI_TOKEN_HOST,
|
||||
WSI_TOKEN_CONNECTION,
|
||||
WSI_TOKEN_KEY1,
|
||||
WSI_TOKEN_KEY2,
|
||||
WSI_TOKEN_PROTOCOL,
|
||||
WSI_TOKEN_UPGRADE,
|
||||
WSI_TOKEN_ORIGIN,
|
||||
WSI_TOKEN_CHALLENGE,
|
||||
|
||||
/* always last real token index*/
|
||||
WSI_TOKEN_COUNT,
|
||||
/* parser state additions */
|
||||
WSI_TOKEN_NAME_PART,
|
||||
WSI_TOKEN_SKIPPING,
|
||||
WSI_TOKEN_SKIPPING_SAW_CR,
|
||||
WSI_PARSING_COMPLETE
|
||||
};
|
||||
struct libwebsocket;
|
||||
|
||||
extern int libwebsocket_create_server(int port,
|
||||
int (*callback)(struct libwebsocket *,
|
||||
enum libwebsocket_callback_reasons));
|
||||
|
||||
struct lws_tokens {
|
||||
char * token;
|
||||
int token_len;
|
||||
};
|
||||
|
||||
struct libwebsocket {
|
||||
|
||||
/* set these up before calling libwebsocket_init */
|
||||
|
||||
int (*websocket_established_callback)(struct libwebsocket *);
|
||||
int (*websocket_closed_callback)(struct libwebsocket *);
|
||||
int (*websocket_send_callback)(struct libwebsocket *);
|
||||
int (*websocket_receive_callback)(struct libwebsocket *);
|
||||
|
||||
/* these are all opaque and maintained by the library */
|
||||
|
||||
enum lws_connection_states state;
|
||||
|
||||
char name_buffer[LWS_MAX_HEADER_NAME_LENGTH];
|
||||
int name_buffer_pos;
|
||||
int current_alloc_len;
|
||||
enum lws_token_indexes parser_state;
|
||||
struct lws_tokens utf8_token[WSI_TOKEN_COUNT];
|
||||
char * response;
|
||||
int response_length;
|
||||
|
||||
int sock;
|
||||
};
|
||||
|
||||
|
||||
extern int libwebsocket_init(struct libwebsocket *wsi, int port);
|
||||
|
||||
extern int libwebsocket_write(struct libwebsocket *, void *buf, size_t len);
|
||||
|
|
55
test-server.c
Normal file
55
test-server.c
Normal file
|
@ -0,0 +1,55 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "libwebsockets.h"
|
||||
|
||||
#define PORT 7681
|
||||
|
||||
int websocket_callback(struct libwebsocket * wsi,
|
||||
enum libwebsocket_callback_reasons reason)
|
||||
{
|
||||
int n;
|
||||
char buf[256];
|
||||
static int bump;
|
||||
|
||||
switch (reason) {
|
||||
case LWS_CALLBACK_ESTABLISHED:
|
||||
fprintf(stderr, "Websocket connection established\n");
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLOSED:
|
||||
fprintf(stderr, "Websocket connection closed\n");
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_SEND:
|
||||
sleep(1);
|
||||
n = sprintf(buf, "%d\n", bump++);
|
||||
n = libwebsocket_write(wsi, buf, n);
|
||||
if (n < 0) {
|
||||
fprintf(stderr, "ERROR writing to socket");
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RECEIVE:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main(int argv, char **argc)
|
||||
{
|
||||
if (libwebsocket_create_server(PORT, websocket_callback) < 0) {
|
||||
fprintf(stderr, "libwebsocket init failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Listening on port %d\n", PORT);
|
||||
|
||||
while (1)
|
||||
sleep(1);
|
||||
|
||||
return 0;
|
||||
}
|
39
test.html
Normal file
39
test.html
Normal file
|
@ -0,0 +1,39 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset=utf-8 />
|
||||
<title>Minimal Websocket message sender</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script>
|
||||
var pos = 0;
|
||||
|
||||
var socket = new WebSocket("ws://127.0.0.1:7681");
|
||||
|
||||
try {
|
||||
// alert('<p class="event">Socket Status: '+socket.readyState);
|
||||
|
||||
socket.onopen = function(){
|
||||
alert('<p class="event">Socket Status: '+socket.readyState+' (open)');
|
||||
}
|
||||
|
||||
socket.onmessage = got_packet;
|
||||
|
||||
socket.onclose = function(){
|
||||
alert('<p class="event">Socket Status: (Closed)');
|
||||
}
|
||||
} catch(exception){
|
||||
alert('<p>Error'+exception);
|
||||
}
|
||||
|
||||
function got_packet(msg){
|
||||
// alert('got packet' + msg);
|
||||
|
||||
document.write(msg.data + "\n");
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Reference in a new issue