i now am a judge
and a good judge too
This commit is contained in:
parent
1cb5c464bb
commit
4319c22ea1
2 changed files with 149 additions and 32 deletions
137
src/wsock.c
137
src/wsock.c
|
@ -1,5 +1,30 @@
|
|||
#include "wsock.h"
|
||||
|
||||
/** UTILITIES **/
|
||||
/*****************/
|
||||
|
||||
#define WS_REORDER_BUFLEN (sizeof(long double))
|
||||
|
||||
inline int _sys_is_net_order() {
|
||||
return ((char*)(0xB00B))[0] == 0xB0;
|
||||
}
|
||||
|
||||
void swap_order(char* in, int length) {
|
||||
if(_sys_is_net_order() || length > WS_REORDER_BUFLEN)
|
||||
return;
|
||||
|
||||
char buf[WS_REORDER_BUFLEN];
|
||||
for(int i = 0; i < length; ++i)
|
||||
buf[i] = in[length - i - 1];
|
||||
memcpy(in, buf, length);
|
||||
}
|
||||
|
||||
void swap_order_copy(char* in, char* out, int length) {
|
||||
memcpy(out, in, length);
|
||||
swap_order(out, length);
|
||||
}
|
||||
|
||||
|
||||
/** DATA BUFFER **/
|
||||
/*******************/
|
||||
|
||||
|
@ -27,48 +52,67 @@ void buffer_append
|
|||
(buffer_t* buf, const char* data, int length)
|
||||
{
|
||||
if(buf->data != NULL) {
|
||||
if(buf->next == NULL)
|
||||
buf->next = buffer_create();
|
||||
buffer_append(buf->next, data, length);
|
||||
}
|
||||
|
||||
} else {
|
||||
buf->data = malloc(length);
|
||||
strncpy(buf->data, data, length);
|
||||
buf->length = length;
|
||||
}
|
||||
}
|
||||
|
||||
void buffer_append_str(buffer_t* buf, const char* data) {
|
||||
buffer_append(buf, data, strlen(data));
|
||||
}
|
||||
|
||||
void _buffer_read(buffer_t* buf, char* out) {
|
||||
int _buffer_read(buffer_t* buf, char* out, int n) {
|
||||
int i = 0;
|
||||
while(buf != NULL) {
|
||||
while(buf != NULL && (!n || (n && i < n))) {
|
||||
if(!n || buf->length <= n - i) {
|
||||
strncpy(out + i, buf->data, buf->length);
|
||||
i += buf->length;
|
||||
buf = buf->next;
|
||||
} else if(n && buf->length > n - i) {
|
||||
strncpy(out + i, buf->data, n - i);
|
||||
i += n - i;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int buffer_peek(buffer_t* buf, char* out, int length) {
|
||||
return _buffer_read(buf, out, length);
|
||||
}
|
||||
|
||||
int buffer_peek_str(buffer_t* buf, char* out, int length) {
|
||||
int read = _buffer_read(buf, out, length);
|
||||
out[read] = '\0';
|
||||
return read;
|
||||
}
|
||||
|
||||
int buffer_read(buffer_t* buf, char** out) {
|
||||
int length = buffer_length(buf);
|
||||
*out = malloc(length);
|
||||
|
||||
_buffer_read(buf, *out);
|
||||
_buffer_read(buf, *out, 0);
|
||||
return length;
|
||||
}
|
||||
|
||||
int buffer_read_str(buffer_t* buf, char** out) {
|
||||
int length = buffer_length(buf);
|
||||
*out = malloc(length + 1);
|
||||
out[length] = '\0';
|
||||
(*out)[length] = '\0';
|
||||
|
||||
_buffer_read(buf, *out);
|
||||
_buffer_read(buf, *out, 0);
|
||||
return length;
|
||||
}
|
||||
|
||||
int buffer_flush(buffer_t* buf, char** out) {
|
||||
int length = buffer_read(buf, out);
|
||||
buffer_clear(buf);
|
||||
return out;
|
||||
return length;
|
||||
}
|
||||
|
||||
int buffer_flush_str(buffer_t* buf, char** out) {
|
||||
|
@ -105,6 +149,56 @@ void buffer_free(buffer_t* buf) {
|
|||
/** WEB SOCKET **/
|
||||
/******************/
|
||||
|
||||
typedef struct {
|
||||
uint8_t fin, opcode, masked, head_length;
|
||||
uint8_t mask[4];
|
||||
uint64_t body_length;
|
||||
} _ws_head_t;
|
||||
|
||||
typedef enum {
|
||||
WS_CONT = 0x0,
|
||||
WS_TEXT = 0x1,
|
||||
WS_BIN = 0x2,
|
||||
WS_CLOSE = 0x8,
|
||||
WS_PING = 0x9,
|
||||
WS_PONG = 0xA
|
||||
} _ws_opcode_t;
|
||||
|
||||
int _wsock_header_length(char* head) {
|
||||
return 2
|
||||
+ ((head[1] & 0x80) == 0 ? 0 : 4)
|
||||
+ ((head[1] & 0x7F) < 0x7E ? 0
|
||||
: ((head[1] & 0x7F) == 0x7E ? 2 : 8));
|
||||
}
|
||||
|
||||
int _wsock_read_header(char* head, _ws_head_t* out) {
|
||||
out->head_length = _wsock_header_length(head);
|
||||
out->fin = 0x80 & head[0];
|
||||
out->opcode = 0x0F & head[0];
|
||||
out->masked = 0x80 & head[1];
|
||||
|
||||
if((head[0] & 0x70) != 0)
|
||||
return -1;
|
||||
if((head[0] & 0x0F) > 0x2 && (head[0] & 0x0F) < 0x8)
|
||||
return -1;
|
||||
if((head[0] & 0x0F) > 0xA && (head[0] & 0x0F) <= 0xF)
|
||||
return -1;
|
||||
|
||||
int mask_start;
|
||||
if((head[1] & 0x7F) < 0x7E) {
|
||||
out->body_length = head[1] & 0x7F;
|
||||
mask_start = 2;
|
||||
} else if((head[1] & 0x7F) == 0x7E) {
|
||||
swap_order_copy(head[2], (char*)out->body_length, 2);
|
||||
mask_start = 4;
|
||||
} else {
|
||||
swap_order_copy(head[2], (char*)out->body_length, 8);
|
||||
mask_start = 10;
|
||||
}
|
||||
if(out->masked)
|
||||
memcpy(out->mask, head + mask_start, 4);
|
||||
}
|
||||
|
||||
wsock_t* wsock_open
|
||||
(const char* host, const char* path, uint16_t port)
|
||||
{
|
||||
|
@ -153,8 +247,8 @@ wsock_t* wsock_open
|
|||
pfd.fd = sock;
|
||||
pfd.events = POLLIN;
|
||||
|
||||
char* end;
|
||||
int total = 0;
|
||||
char* end;
|
||||
while((end = strstr(s_shake, "\r\n\r\n")) == NULL) {
|
||||
if(total + 1 >= sizeof(s_shake)
|
||||
|| poll(&pfd, 1, 5000) <= 0)
|
||||
|
@ -163,11 +257,14 @@ wsock_t* wsock_open
|
|||
return NULL;
|
||||
}
|
||||
|
||||
total += recv(sock, s_shake + total,
|
||||
sizeof(s_shake) - total - 1, 0);
|
||||
total = recv(sock, s_shake, sizeof(s_shake) - 1, MSG_PEEK);
|
||||
s_shake[total] = '\0';
|
||||
}
|
||||
|
||||
total = end - s_shake + 3;
|
||||
recv(sock, s_shake, total, 0);
|
||||
s_shake[total + 1] = '\0';
|
||||
|
||||
const char resp_check[] = "HTTP/1.1 101 Switching Protocols";
|
||||
if(strncmp(s_shake, resp_check, sizeof(resp_check) - 1) != 0)
|
||||
{
|
||||
|
@ -178,11 +275,8 @@ wsock_t* wsock_open
|
|||
wsock_t* wsock = malloc(sizeof(wsock_t));
|
||||
wsock->sock = sock;
|
||||
wsock->mode = WS_BLOCK;
|
||||
wsock->buffer = buffer_create();
|
||||
if(total - 1 != (end - s_shake) + 3)
|
||||
buffer_append(wsock->buffer, end + 4,
|
||||
total - 1 - ((end - s_shake) + 3));
|
||||
|
||||
wsock->recv_buf = buffer_create();
|
||||
wsock->send_buf = buffer_create();
|
||||
return wsock;
|
||||
}
|
||||
|
||||
|
@ -194,7 +288,15 @@ int wsock_mode_get(wsock_t* ws) {
|
|||
return ws->mode;
|
||||
}
|
||||
|
||||
int wsock_recv(wsock_t* ws, char** out) {
|
||||
char buffer[4096];
|
||||
int got = 0;
|
||||
do {
|
||||
//if((ws->mode & WS_NOBLOCK) != 0)
|
||||
|
||||
} while((ws->mode & WS_FULL_RECV) != 0);
|
||||
return got;
|
||||
}
|
||||
|
||||
int wsock_is_open(wsock_t* ws) {
|
||||
return ws->sock >= 0;
|
||||
|
@ -203,7 +305,8 @@ int wsock_is_open(wsock_t* ws) {
|
|||
void wsock_close(wsock_t* ws) {
|
||||
// todo: send close frame
|
||||
shutdown(ws->sock, SHUT_RDWR);
|
||||
buffer_free(ws->buffer);
|
||||
buffer_free(ws->recv_buf);
|
||||
buffer_free(ws->send_buf);
|
||||
free(ws);
|
||||
}
|
||||
|
||||
|
|
28
src/wsock.h
28
src/wsock.h
|
@ -1,12 +1,20 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/poll.h>
|
||||
#include <netdb.h>
|
||||
|
||||
/** UTILITIES **/
|
||||
/*****************/
|
||||
|
||||
void swap_order(char*, int);
|
||||
void swap_order_copy(char*, char*, int);
|
||||
|
||||
|
||||
/** DATA BUFFER **/
|
||||
/*******************/
|
||||
|
||||
|
@ -24,10 +32,12 @@ int buffer_length(buffer_t*);
|
|||
void buffer_append(buffer_t*, const char*, int);
|
||||
void buffer_append_str(buffer_t*, const char*);
|
||||
|
||||
char* buffer_read(buffer_t*, int*);
|
||||
char* buffer_read_str(buffer_t*, int*);
|
||||
char* buffer_flush(buffer_t*, int*);
|
||||
char* buffer_flush_str(buffer_t*, int*);
|
||||
int buffer_peek(buffer_t*, char*, int);
|
||||
int buffer_peek_str(buffer_t*, char*, int);
|
||||
int buffer_read(buffer_t*, char**);
|
||||
int buffer_read_str(buffer_t*, char**);
|
||||
int buffer_flush(buffer_t*, char**);
|
||||
int buffer_flush_str(buffer_t*, char**);
|
||||
|
||||
void buffer_clear(buffer_t*);
|
||||
void buffer_free(buffer_t*);
|
||||
|
@ -44,7 +54,9 @@ typedef enum {
|
|||
// block until a full packet is received
|
||||
WS_FULL_RECV = 2,
|
||||
// block until a full packet is sent
|
||||
WS_FULL_SEND = 4
|
||||
WS_FULL_SEND = 4,
|
||||
// receive text frames as binary
|
||||
WS_RECV_ALL_BIN = 8
|
||||
} ws_mode_t;
|
||||
// mode options that are not mutually exclusive can be
|
||||
// concatenated using the OR (|) operator. note that
|
||||
|
@ -73,14 +85,16 @@ typedef enum {
|
|||
|
||||
typedef struct {
|
||||
int sock, mode;
|
||||
buffer_t* buffer;
|
||||
buffer_t *recv_buf, *send_buf;
|
||||
} wsock_t;
|
||||
|
||||
wsock_t* wsock_open(const char*, const char*, uint16_t);
|
||||
void wsock_mode_set(wsock_t*, int);
|
||||
int wsock_mode_get(wsock_t*);
|
||||
|
||||
int wsock_recv(wsock_t*,
|
||||
int wsock_recv(wsock_t*, char**);
|
||||
int wsock_send(wsock_t*, char*, int);
|
||||
int wsock_send_str(wsock_t*, char*);
|
||||
|
||||
int wsock_is_open(wsock_t*);
|
||||
void wsock_close(wsock_t*);
|
||||
|
|
Loading…
Reference in a new issue