clii/src/wsock.h
reemo 1b775f59cc i finally get to go home
not touching a computer for a while weow
2023-12-28 18:08:23 +00:00

139 lines
3.8 KiB
C

#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>
#include <errno.h>
/** UTILITIES **/
/*****************/
#define __MAX(A, B) ((A) > (B) ? (A) : (B))
#define __MIN(A, B) ((A) < (B) ? (A) : (B))
void swap_order(char*, int);
void swap_order_copy(char*, char*, int);
/** DATA BUFFER **/
/*******************/
struct buffer_t {
char* data;
int length;
struct buffer_t* next;
};
typedef struct buffer_t buffer_t;
buffer_t* buffer_create();
int buffer_is_empty(buffer_t*);
int buffer_length(buffer_t*);
void buffer_append(buffer_t*, const char*, int);
void buffer_append_str(buffer_t*, const char*);
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*);
/** WEB SOCKET **/
/******************/
#define WS_MAX_LENGTH 0xFFFFFF
#define WS_INTERNAL_BUFLEN 4096
#define WS_OP_UNDEF 0xFF
#define WS_OP_IS_CTRL(A) (A >= WS_CLOSE)
typedef enum {
// block on system calls
WS_BLOCK = 0,
// do not block on system calls
WS_NOBLOCK = 1,
// block until a full packet is received
WS_FULL_RECV = 2,
// block until a full packet is sent
WS_FULL_SEND = 4,
// receive text frames as binary
WS_RECV_ALL_BIN = 8,
// send text frames as binary
WS_SEND_ALL_BIN = 16
} ws_mode_t;
// mode options that are not mutually exclusive can be
// concatenated using the OR (|) operator. note that
// WS_BLOCK and WS_NOBLOCK control blocking only on the
// system socket functions, whereas WS_FULL_RECV and
// WS_FULL_SEND will block on the protocol level, until
// a packet is fully sent or received
// for example, WS_BLOCK alone will block until data is
// available, but will immediately return nothing if the
// data received is not a full packet. however, using
// WS_BLOCK | WS_FULL_RECV will block until data is
// available, and then until a full websocket packet is
// fully received, after which the data is then returned.
// WS_NOBLOCK behaves in the same way except the system
// calls will not block, but with WS_FULL_RECV enabled
// it will then block until a full packet is received
// currently WS_FULL_SEND is set to be always enabled
// when the mode is changed because i do not currently
// see a need for partial sends in this client, thus
// all sends will block until the full packet is sent
// over the wire. if anyone else modifying this client
// has an EXTREME THIRST for partial sends, they can
// implement this behavior themselves
// !!! VERY IMPORTANT NOTE !!!
// if using WS_FULL_RECV, wsock_recv() can STILL RETURN 0
// this happens when a control frame is received from the
// server and is handled by this library. in order for
// select() or poll() to function correctly when used
// outside of the library this is a necessary behavior.
// please check for a 0 return and handle appropriately
typedef struct {
uint8_t fin, opcode, first_opcode,
masked, mask[4], head_length;
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;
typedef struct {
int sock, mode;
_ws_head_t head_buf;
buffer_t *recv_buf, *frag_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*, char**);
int wsock_send_raw(wsock_t*, int, char*, uint64_t);
int wsock_send(wsock_t*, char*, int);
int wsock_send_str(wsock_t*, char*);
int wsock_ping(wsock_t*, char*);
int wsock_is_open(wsock_t*);
void wsock_close(wsock_t*);
void wsock_free(wsock_t*);