forked from billywhizz/ws-uv
-
Notifications
You must be signed in to change notification settings - Fork 1
/
websock.h
171 lines (155 loc) · 4.64 KB
/
websock.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include "uv.h"
#include "http_parser.h"
#include "wsparser.h"
#include "sha1.h"
#define MAX_HEADERS 20
#define MAX_ELEMENT_SIZE 500
#define MAX_URL_SIZE 255
typedef struct {
uv_write_t req;
uv_buf_t buf;
} write_req_t;
typedef struct request request;
struct request {
uint64_t id;
char url[MAX_URL_SIZE];
enum http_method method;
unsigned short http_major;
unsigned short http_minor;
int num_headers;
enum { NONE=0, FIELD, VALUE } last_header_element;
char headers [MAX_HEADERS][2][MAX_ELEMENT_SIZE];
char wskey[61];
uint8_t upgrade;
uint8_t handshake;
uint8_t keepalive;
};
typedef struct _context _context;
struct _context {
int fd;
http_parser* parser;
ws_parser* wsparser;
request* request;
uv_stream_t* handle;
};
static inline void context_init (uv_stream_t* handle);
static inline void context_free (uv_handle_t* handle);
static int ws_header_cb(ws_parser* p);
static int ws_chunk_cb(ws_parser* p, const char* at, size_t len);
static int ws_complete_cb(ws_parser* p);
static int message_begin_cb (http_parser *p);
static int url_cb (http_parser *p, const char *buf, size_t len);
static int header_field_cb (http_parser *p, const char *buf, size_t len);
static int header_value_cb (http_parser *p, const char *buf, size_t len);
static int headers_complete_cb (http_parser *p);
static int message_complete_cb (http_parser *p);
static void on_connection(uv_stream_t* server, int status);
static void after_read(uv_stream_t* handle, ssize_t nread, uv_buf_t buf);
static void after_write(uv_write_t* req, int status);
static void on_close(uv_handle_t* peer);
static void after_shutdown(uv_shutdown_t* req, int status);
static uv_buf_t echo_alloc(uv_handle_t* handle, size_t suggested_size);
static int server_start(int port);
static http_parser_settings settings =
{
.on_message_begin = message_begin_cb,
.on_header_field = header_field_cb,
.on_header_value = header_value_cb,
.on_url = url_cb,
.on_headers_complete = headers_complete_cb,
.on_message_complete = message_complete_cb
};
static ws_settings wssettings = {
.on_header = ws_header_cb,
.on_chunk = ws_chunk_cb,
.on_complete = ws_complete_cb,
};
static uv_tcp_t tcpServer;
static uv_loop_t* loop;
static const char* wshash = " 258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
static char r400[96];
static char r403[90];
static char r101[129];
static void xxdprint(const char *buff, uint64_t offset, uint64_t size) {
uint64_t i = offset;
uint64_t j;
while(i < size)
{
uint8_t val = buff[i] & 0xff;
if(i%8==0 && i > 0) {
printf(" ");
}
if(i%16==0) {
if(i>0) {
printf(" ");
for(j=i-16;j<i;j++) {
int vv = buff[j];
if(vv > 0x20 && vv < 0x7e) {
printf("%c", vv);
}
else {
printf(".");
}
}
printf("\n");
}
printf("%.8lu: ", i);
}
printf("%.2x ", val);
i++;
}
if(size%16!=0) {
for(j=0; j<(16-(size%16)); j++) {
printf(" ");
}
printf(" ");
if(size%16<=8) printf(" ");
for(j=i-(size%16);j<i;j++) {
int vv = buff[j];
if(vv > 0x20 && vv < 0x7e) {
printf("%c", vv);
}
else {
printf(".");
}
}
}
printf("\n");
}
static void print_request(request* req) {
fprintf(stderr, "---------------------------------------------------\n");
fprintf(stderr, "id: %lu\n", req->id);
fprintf(stderr, "method: %i\n", req->method);
fprintf(stderr, "major: %i\n", req->http_major);
fprintf(stderr, "minor: %i\n", req->http_minor);
fprintf(stderr, "url: %s\n", req->url);
fprintf(stderr, "upgrade: %i\n", req->upgrade);
fprintf(stderr, "keepalive: %i\n", req->keepalive);
fprintf(stderr, "wskey: %s\n", req->wskey);
fprintf(stderr, "handshake: %i\n", req->handshake);
fprintf(stderr, "headers: %i\n", req->num_headers);
int i=0;
for(i=0; i<req->num_headers; i++) {
fprintf(stderr, "\tname: %s\n", req->headers[i][0]);
fprintf(stderr, "\tvalue: %s\n", req->headers[i][1]);
}
fprintf(stderr, "---------------------------------------------------\n");
}
static void print_ws_header(ws_header* header) {
fprintf(stderr, "fin: %i\n", header->fin);
fprintf(stderr, "rsv0: %i\n", header->reserved[0]);
fprintf(stderr, "rsv1: %i\n", header->reserved[1]);
fprintf(stderr, "rsv2: %i\n", header->reserved[2]);
fprintf(stderr, "opcode: %i\n", header->opcode);
fprintf(stderr, "length: %i\n", header->length);
fprintf(stderr, "masking: %i\n", header->mask);
fprintf(stderr, "mask0: %i\n", header->maskkey[0]);
fprintf(stderr, "mask1: %i\n", header->maskkey[1]);
fprintf(stderr, "mask2: %i\n", header->maskkey[2]);
fprintf(stderr, "mask3: %i\n", header->maskkey[3]);
}