wsock handshake works
This commit is contained in:
parent
53272e629d
commit
2766e50f47
4 changed files with 188 additions and 5 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -36,6 +36,7 @@
|
||||||
*.i*86
|
*.i*86
|
||||||
*.x86_64
|
*.x86_64
|
||||||
*.hex
|
*.hex
|
||||||
|
clii
|
||||||
|
|
||||||
# Debug files
|
# Debug files
|
||||||
*.dSYM/
|
*.dSYM/
|
||||||
|
@ -51,4 +52,4 @@ modules.order
|
||||||
Module.symvers
|
Module.symvers
|
||||||
Mkfile.old
|
Mkfile.old
|
||||||
dkms.conf
|
dkms.conf
|
||||||
|
*.swp
|
||||||
|
|
|
@ -67,6 +67,7 @@ int main(int argc, char** argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Connecting to Flashii ...\n");
|
printf("Connecting to Flashii ...\n");
|
||||||
|
wsock_t* sock = wsock_open(FII_ADDR, "/", 80);
|
||||||
|
|
||||||
for(;;);
|
for(;;);
|
||||||
|
|
||||||
|
|
175
src/wsock.c
175
src/wsock.c
|
@ -1,3 +1,178 @@
|
||||||
#include "wsock.h"
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
14
src/wsock.h
14
src/wsock.h
|
@ -1,5 +1,10 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/poll.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
|
||||||
/** DATA BUFFER **/
|
/** DATA BUFFER **/
|
||||||
|
@ -14,6 +19,7 @@ typedef struct buffer_t buffer_t;
|
||||||
|
|
||||||
buffer_t* buffer_create();
|
buffer_t* buffer_create();
|
||||||
|
|
||||||
|
int buffer_is_empty(buffer_t*);
|
||||||
int buffer_length(buffer_t*);
|
int buffer_length(buffer_t*);
|
||||||
void buffer_append(buffer_t*, const char*, int);
|
void buffer_append(buffer_t*, const char*, int);
|
||||||
void buffer_append_str(buffer_t*, const char*);
|
void buffer_append_str(buffer_t*, const char*);
|
||||||
|
@ -47,15 +53,15 @@ typedef enum {
|
||||||
// WS_FULL_SEND will block on the protocol level, until
|
// WS_FULL_SEND will block on the protocol level, until
|
||||||
// a packet is fully sent or received
|
// a packet is fully sent or received
|
||||||
|
|
||||||
// for example, WS_BLOCK alone with block until data is
|
// for example, WS_BLOCK alone will block until data is
|
||||||
// available, but will immediately return nothing if the
|
// available, but will immediately return nothing if the
|
||||||
// data received is not a full packet. however, using
|
// data received is not a full packet. however, using
|
||||||
// WS_BLOCK | WS_FULL_RECV will block until data is
|
// WS_BLOCK | WS_FULL_RECV will block until data is
|
||||||
// available, and then until a full websocket packet is
|
// available, and then until a full websocket packet is
|
||||||
// fully constructed, after which the data is returned.
|
// fully received, after which the data is then returned.
|
||||||
// noblock behaves in the same way except the system
|
// WS_NOBLOCK behaves in the same way except the system
|
||||||
// calls will not block, but with WS_FULL_RECV enabled
|
// calls will not block, but with WS_FULL_RECV enabled
|
||||||
// it will then block until a full packet is constructed
|
// it will then block until a full packet is received
|
||||||
|
|
||||||
// currently WS_FULL_SEND is set to be always enabled
|
// currently WS_FULL_SEND is set to be always enabled
|
||||||
// when the mode is changed because i do not currently
|
// when the mode is changed because i do not currently
|
||||||
|
|
Loading…
Reference in a new issue