From c07a007731d49f7a204f3187e4ed461e9341e2e7 Mon Sep 17 00:00:00 2001 From: reemo Date: Wed, 20 Dec 2023 18:21:13 -0600 Subject: [PATCH] HOLY SHIT IT WORKS EXCEPT I GET A SIGABRT WHEN THE LINE IS SILENT GOD DAMNIT --- src/main.c | 11 ++++++- src/wsock.c | 85 +++++++++++++++++++++++++++++++++++++++++++---------- src/wsock.h | 7 +++-- 3 files changed, 85 insertions(+), 18 deletions(-) diff --git a/src/main.c b/src/main.c index 84fedcd..19c7415 100644 --- a/src/main.c +++ b/src/main.c @@ -67,10 +67,19 @@ int main(int argc, char** argv) { return -1; } + char buf[2048], *get; printf("Connecting to Flashii ...\n"); wsock_t* sock = wsock_open(FII_ADDR, "/", 80); + printf("Authenticating ...\n"); - for(;;); + sprintf(buf, "1\tMisuzu\t%s", _G.session); + wsock_send_str(sock, buf); + + for(;;) { + wsock_recv(sock, &get); + printf("%s\n", get); + free(get); + } initscr(); raw(); noecho(); diff --git a/src/wsock.c b/src/wsock.c index 10a226f..5dd2afe 100644 --- a/src/wsock.c +++ b/src/wsock.c @@ -5,8 +5,9 @@ #define WS_REORDER_BUFLEN (sizeof(long double)) -inline int _sys_is_net_order() { - return ((char*)(0xB00B))[0] == 0xB0; +int _sys_is_net_order() { + const uint16_t test = 0xB00B; + return ((char*)&test)[0] == 0xB0; } void swap_order(char* in, int length) { @@ -176,15 +177,15 @@ int _wsock_read_header(char* head, _ws_head_t* out) { if((head[0] & 0x70) != 0 || ((head[0] & 0x0F) > 0x2 && (head[0] & 0x0F) < 0x8) || ((head[0] & 0x0F) > 0xA && (head[0] & 0x0F) <= 0xF)) - return -1; + return 0; // invalid parameters check if((out->opcode == WS_CONT && out->first_opcode == WS_OP_UNDEF) || (out->opcode != WS_CONT && - !WS_IS_OP_CTRL(out->opcode) && + !WS_OP_IS_CTRL(out->opcode) && out->first_opcode != WS_OP_UNDEF) - || (WS_IS_OP_CTRL(out->opcode) && !out->fin)) - return -1; + || (WS_OP_IS_CTRL(out->opcode) && !out->fin)) + return 0; // cache first opcode of fragmented data set if(out->opcode != WS_CONT && !WS_OP_IS_CTRL(out->opcode)) out->first_opcode = out->opcode; @@ -194,14 +195,16 @@ int _wsock_read_header(char* head, _ws_head_t* out) { 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); + swap_order_copy(head + 2, (char*)&out->body_length, 2); mask_start = 4; } else { - swap_order_copy(head[2], (char*)out->body_length, 8); + swap_order_copy(head + 2, (char*)&out->body_length, 8); mask_start = 10; } if(out->masked) memcpy(out->mask, head + mask_start, 4); + + return 1; } void _wsock_mask(char* mask, char* msg, int length) { @@ -252,7 +255,7 @@ wsock_t* wsock_open path, host, port ); - if(send(sock, s_shake, strlen(s_shake), 0) <= 0) { + if(send(sock, s_shake, strlen(s_shake), MSG_NOSIGNAL) <= 0) { shutdown(sock, SHUT_RDWR); return NULL; } @@ -276,7 +279,7 @@ wsock_t* wsock_open s_shake[total] = '\0'; } - total = end - s_shake + 3; + total = (end - s_shake) + 4; recv(sock, s_shake, total, 0); s_shake[total + 1] = '\0'; @@ -377,11 +380,12 @@ int wsock_recv(wsock_t* ws, char** out) { } char* body; - int body_length = buffer_flush(ws->recv_buf, &packet); + int body_length = buffer_flush(ws->recv_buf, &body); if(body != NULL) { if(ws->head_buf.masked) - _ws_mask(body, ws->head_buf.mask, body_length); - if(!WS_PACKET_IS_CTRL(ws->head_buf.opcode)) { + _wsock_mask((char*)ws->head_buf.mask, + body, body_length); + if(!WS_OP_IS_CTRL(ws->head_buf.opcode)) { buffer_append(ws->frag_buf, body, body_length); free(body); } @@ -431,13 +435,63 @@ int wsock_recv(wsock_t* ws, char** out) { return got; } +// todo: support sending fragments at some point int wsock_send_raw - (wsock_t* ws, int opcode, char* body, int length) + (wsock_t* ws, int opcode, char* body, uint64_t length) { if(!wsock_is_open(ws)) return -1; + char header[14], *mask; + int header_bsize_len = + (length < 0x7E) ? 0 : + ((length <= 0xFFFF) ? 2 : 8); + int header_length = + 2 + (length > 0 ? 4 : 0) + header_bsize_len; + header[0] = 0x80 | opcode; + header[1] = 0x80 | ((length < 0x7E) ? length + : (length <= 0xFFFF ? 0x7E : 0x7F)); + uint16_t length_u16 = (uint16_t)length; + if(header_bsize_len > 0) + swap_order_copy( + (header_bsize_len == 2 + ? (char*)&length_u16 : (char*)&length), + header + 2, header_bsize_len); + + if(length > 0) { + mask = header + 2 + header_bsize_len; + _wsock_gen_mask(mask); + } + + if(send(ws->sock, header, + header_length, MSG_NOSIGNAL) <= 0) + { + wsock_close(ws); + return -1; + } + + if(length > 0) { + _wsock_mask(mask, body, length); + if(send(ws->sock, body, length, MSG_NOSIGNAL) <= 0) { + wsock_close(ws); + return -1; + } + _wsock_mask(mask, body, length); + } + + return header_length + length; +} + +int wsock_send(wsock_t* ws, char* body, int length) { + return wsock_send_raw(ws, WS_BIN, body, length); +} + +int wsock_send_str(wsock_t* ws, char* body) { + if(ws->mode & WS_SEND_ALL_BIN) + return wsock_send(ws, body, strlen(body)); + else + return wsock_send_raw(ws, WS_TEXT, body, strlen(body)); } int wsock_is_open(wsock_t* ws) { @@ -449,7 +503,8 @@ void wsock_close(wsock_t* ws) { return; const char close_frame[2] = {0x88, 0x00}; - send(ws->sock, close_frame, sizeof(close_frame)); + send(ws->sock, close_frame, + sizeof(close_frame), MSG_NOSIGNAL); shutdown(ws->sock, SHUT_RDWR); ws->sock = -1; } diff --git a/src/wsock.h b/src/wsock.h index b8d160c..c539a3c 100644 --- a/src/wsock.h +++ b/src/wsock.h @@ -7,6 +7,7 @@ #include #include #include +#include /** UTILITIES **/ /*****************/ @@ -64,7 +65,9 @@ typedef enum { // block until a full packet is sent WS_FULL_SEND = 4, // receive text frames as binary - WS_RECV_ALL_BIN = 8 + 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 @@ -117,7 +120,7 @@ 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*, int); +int wsock_send_raw(wsock_t*, int, char*, uint64_t); int wsock_send(wsock_t*, char*, int); int wsock_send_str(wsock_t*, char*);