diff options
-rw-r--r-- | index.html | 11 | ||||
-rw-r--r-- | websocksy.c | 98 | ||||
-rw-r--r-- | websocksy.h | 12 |
3 files changed, 98 insertions, 23 deletions
diff --git a/index.html b/index.html new file mode 100644 index 0000000..c0af329 --- /dev/null +++ b/index.html @@ -0,0 +1,11 @@ +<html> + <head> + <script type="text/javascript"> + function init(){ + var webSocket = new WebSocket("ws://localhost:8001/"); + } + </script> + </head> + <body onload="init();"> + </body> +</html> diff --git a/websocksy.c b/websocksy.c index dba8124..cc5b9e0 100644 --- a/websocksy.c +++ b/websocksy.c @@ -14,6 +14,7 @@ /* TODO * - TLS * - config parsing + * - Prevent http overrun */ static size_t socks = 0; @@ -120,13 +121,33 @@ int network_socket(char* host, char* port, int socktype, int listener){ return fd; } +int ws_close(websocket* ws){ + size_t p; + + if(ws->fd >= 0){ + close(ws->fd); + ws->fd = -1; + } + + for(p = 0; p < ws->protocols; p++){ + if(ws->protocol[p].fd >= 0){ + close(ws->protocol[p].fd); + ws->protocol[p].fd = -1; + free(ws->protocol[p].name); + ws->protocol[p].name = NULL; + } + } + + ws->read_buffer_offset = 0; + + return 0; +} + int ws_accept(int listen_fd){ size_t n = 0; - struct sockaddr_storage sa_storage; - socklen_t sa_length; websocket ws = { - .fd = accept(listen_fd, (struct sockaddr*)&sa_storage, &sa_length) + .fd = accept(listen_fd, NULL, NULL) }; //try to find a slot to occupy @@ -154,34 +175,65 @@ int ws_accept(int listen_fd){ } int ws_data(websocket* ws){ - //TODO - return -1; -} + ssize_t bytes_read, u, bytes_left = sizeof(ws->read_buffer) - ws->read_buffer_offset; -int ws_peer_data(websocket* ws, size_t proto){ - //TODO - return -1; -} - -int ws_close(websocket* ws){ - size_t p; - - if(ws->fd >= 0){ - close(ws->fd); - ws->fd = -1; + bytes_read = recv(ws->fd, ws->read_buffer + ws->read_buffer_offset, bytes_left - 1, 0); + if(bytes_read < 0){ + fprintf(stderr, "Failed to receive from websocket: %s\n", strerror(errno)); + ws_close(ws); + return 0; + } + else if(bytes_read == 0){ + //client closed connection + ws_close(ws); + return 0; } - for(p = 0; p < ws->protocols; p++){ - if(ws->protocol[p].fd >= 0){ - close(ws->protocol[p].fd); - ws->protocol[p].fd = -1; - free(ws->protocol[p].name); - } + //terminate new data + ws->read_buffer[ws->read_buffer_offset + bytes_read] = 0; + + switch(ws->state){ + case ws_new: + case ws_http: + //scan for newline, handle line + for(u = 0; u < bytes_read - 1; u++){ + if(!strncmp((char*) ws->read_buffer + ws->read_buffer_offset + u, "\r\n", 2)){ + //terminate line + ws->read_buffer[ws->read_buffer_offset + u] = 0; + + fprintf(stderr, "Line: %s\n", ws->read_buffer); + + //remove from buffer + bytes_read -= (u + 2); + memmove(ws->read_buffer, ws->read_buffer + ws->read_buffer_offset + u + 2, bytes_read); + ws->read_buffer_offset = 0; + + //restart from the beginning + u = -1; + } + } + break; + //case ws_rfc6455: + //TODO parse websocket encap, forward to peer } + //update read buffer offset + ws->read_buffer_offset = bytes_read; + + //disconnect spammy clients + if(sizeof(ws->read_buffer) - ws->read_buffer_offset < 2){ + fprintf(stderr, "Disconnecting misbehaving client\n"); + ws_close(ws); + return 0; + } return 0; } +int ws_peer_data(websocket* ws, size_t proto){ + //TODO + return -1; +} + int main(int argc, char** argv){ fd_set read_fds; size_t n, p; diff --git a/websocksy.h b/websocksy.h index 36a713d..0fc9538 100644 --- a/websocksy.h +++ b/websocksy.h @@ -1,6 +1,14 @@ #include <stdint.h> #include <stdlib.h> +#define WS_MAX_LINE 16384 + +typedef enum { + ws_new = 0, + ws_http, + ws_rfc6455 +} ws_state; + struct { char* host; char* port; @@ -19,6 +27,10 @@ typedef struct { } ws_proto; typedef struct /*_web_socket*/ { + uint8_t read_buffer[WS_MAX_LINE]; + size_t read_buffer_offset; + ws_state state; + int fd; size_t protocols; ws_proto* protocol; |