179 lines
3.3 KiB
C
179 lines
3.3 KiB
C
#include "wsock.h"
|
|
|
|
/** DATA BUFFER **/
|
|
/*******************/
|
|
|
|
buffer_t* buffer_create() {
|
|
buffer_t* buf = malloc(sizeof(buffer_t));
|
|
buf->data = NULL;
|
|
buf->next = NULL;
|
|
buf->length = 0;
|
|
|
|
return buf;
|
|
}
|
|
|
|
int buffer_is_empty(buffer_t* buf) {
|
|
return buf->data == NULL;
|
|
}
|
|
|
|
int buffer_length(buffer_t* buf) {
|
|
if(buf == NULL)
|
|
return 0;
|
|
|
|
return buf->length + buffer_length(buf->next);
|
|
}
|
|
|
|
void buffer_append
|
|
(buffer_t* buf, const char* data, int length)
|
|
{
|
|
if(buf->data != NULL) {
|
|
buf->next = buffer_create();
|
|
buffer_append(buf->next, data, length);
|
|
}
|
|
|
|
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 i = 0;
|
|
while(buf != NULL) {
|
|
strncpy(out + i, buf->data, buf->length);
|
|
i += buf->length;
|
|
}
|
|
}
|
|
|
|
char* buffer_read(buffer_t* buf, int* plen) {
|
|
int length = buffer_length(buf);
|
|
if(plen != NULL)
|
|
*plen = length;
|
|
|
|
char* out = malloc(length);
|
|
_buffer_read(buf, out);
|
|
return out;
|
|
}
|
|
|
|
char* buffer_read_str(buffer_t* buf, int* plen) {
|
|
int length = buffer_length(buf);
|
|
if(plen != NULL)
|
|
*plen = length;
|
|
|
|
char* out = malloc(length + 1);
|
|
out[length] = '\0';
|
|
_buffer_read(buf, out);
|
|
return out;
|
|
}
|
|
|
|
char* buffer_flush(buffer_t* buf, int* plen) {
|
|
char* out = buffer_read(buf, plen);
|
|
buffer_clear(buf);
|
|
return out;
|
|
}
|
|
|
|
char* buffer_flush_str(buffer_t* buf, int* plen) {
|
|
char* out = buffer_read_str(buf, plen);
|
|
buffer_clear(buf);
|
|
return out;
|
|
}
|
|
|
|
void _buffer_clear(buffer_t* buf, int root) {
|
|
if(buf == NULL)
|
|
return;
|
|
_buffer_clear(buf->next, 0);
|
|
|
|
free(buf->data);
|
|
if(!root)
|
|
free(buf);
|
|
else {
|
|
buf->data = NULL;
|
|
buf->next = NULL;
|
|
buf->length = 0;
|
|
}
|
|
}
|
|
|
|
void buffer_clear(buffer_t* buf) {
|
|
_buffer_clear(buf, 1);
|
|
}
|
|
|
|
void buffer_free(buffer_t* buf) {
|
|
buffer_clear(buf);
|
|
free(buf);
|
|
}
|
|
|
|
|
|
/** WEB SOCKET **/
|
|
/******************/
|
|
|
|
wsock_t* wsock_open
|
|
(const char* host, const char* path, uint16_t port)
|
|
{
|
|
char s_port[6];
|
|
sprintf(s_port, "%i", port);
|
|
|
|
int sock;
|
|
struct addrinfo hints, *result, *rp;
|
|
memset(&hints, 0, sizeof(hints));
|
|
hints.ai_family = AF_UNSPEC;
|
|
hints.ai_socktype = SOCK_STREAM;
|
|
hints.ai_flags = 0;
|
|
hints.ai_protocol = 0;
|
|
|
|
if(getaddrinfo(host, s_port, &hints, &result) != 0)
|
|
return NULL;
|
|
for(rp = result; rp != NULL; rp = rp->ai_next) {
|
|
if((sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) == -1)
|
|
continue;
|
|
if(connect(sock, rp->ai_addr, rp->ai_addrlen) != -1)
|
|
break;
|
|
}
|
|
freeaddrinfo(result);
|
|
if(rp == NULL)
|
|
return NULL;
|
|
|
|
// todo: randomize wsock key
|
|
char s_shake[4096];
|
|
sprintf(s_shake,
|
|
"GET %s HTTP/1.1\r\n"
|
|
"Host: %s:%i\r\n"
|
|
"Upgrade: websocket\r\n"
|
|
"Connection: Upgrade\r\n"
|
|
"Sec-WebSocket-Key: AQIDBAUGBwgJCgsMDQ4PEC==\r\n"
|
|
"Sec-WebSocket-Version: 13\r\n\r\n",
|
|
path,
|
|
host, port
|
|
);
|
|
if(send(sock, s_shake, strlen(s_shake), 0) <= 0) {
|
|
shutdown(sock, SHUT_RDWR);
|
|
return NULL;
|
|
}
|
|
s_shake[0] = '\0';
|
|
|
|
struct pollfd pfd;
|
|
pfd.fd = sock;
|
|
pfd.events = POLLIN;
|
|
|
|
char* end;
|
|
int total = 0;
|
|
while((end = strstr(s_shake, "\r\n\r\n")) == NULL) {
|
|
if(total + 1 >= sizeof(s_shake)
|
|
|| poll(&pfd, 1, 5000) <= 0)
|
|
{
|
|
shutdown(sock,SHUT_RDWR);
|
|
return NULL;
|
|
}
|
|
|
|
total += recv(sock, s_shake + total,
|
|
sizeof(s_shake) - total - 1, 0);
|
|
s_shake[total] = '\0';
|
|
}
|
|
|
|
shutdown(sock, SHUT_RDWR);
|
|
return NULL;
|
|
}
|
|
|