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
|
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
char* xstr_lower(char* in){
size_t n;
for(n = 0; n < strlen(in); n++){
in[n] = tolower(in[n]);
}
return in;
}
#include "websocksy.h"
#include "network.c"
#include "ws_proto.c"
/* TODO
* - TLS
* - config parsing
* - Prevent http overrun
*/
static volatile sig_atomic_t shutdown_requested = 0;
void signal_handler(int signum){
shutdown_requested = 1;
}
int usage(char* fn){
fprintf(stderr, "\nwebsocksy - Proxy between websockets and 'real' sockets\n");
fprintf(stderr, "Usage:\n");
fprintf(stderr, "\t%s [-p <port>] [-l <listen address>] [-b <targeting backend>]\n", fn);
return EXIT_FAILURE;
}
int args_parse(int argc, char** argv){
//TODO
return 0;
}
int ws_peer_data(websocket* ws){
//TODO
return -1;
}
int main(int argc, char** argv){
fd_set read_fds;
size_t n;
int listen_fd = -1, status, max_fd;
if(args_parse(argc - 1, argv + 1)){
exit(usage(argv[0]));
}
//open listening socket
listen_fd = network_socket(config.host, config.port, SOCK_STREAM, 1);
if(listen_fd < 0){
exit(usage(argv[0]));
}
signal(SIGINT, signal_handler);
//core loop
while(!shutdown_requested){
FD_ZERO(&read_fds);
FD_SET(listen_fd, &read_fds);
max_fd = listen_fd;
//push all fds to the select set
for(n = 0; n < socks; n++){
if(sock[n].fd >= 0){
FD_SET(sock[n].fd, &read_fds);
if(max_fd < sock[n].fd){
max_fd = sock[n].fd;
}
if(sock[n].peer >= 0){
FD_SET(sock[n].peer, &read_fds);
if(max_fd < sock[n].peer){
max_fd = sock[n].peer;
}
}
}
}
//block until something happens
status = select(max_fd + 1, &read_fds, NULL, NULL, NULL);
if(status < 0){
fprintf(stderr, "Failed to select: %s\n", strerror(errno));
break;
}
else if(status == 0){
//timeout in select - ignore for now
}
else{
//new websocket client
if(FD_ISSET(listen_fd, &read_fds)){
if(ws_accept(listen_fd)){
break;
}
}
//websocket & peer data
for(n = 0; n < socks; n++){
if(sock[n].fd >= 0){
if(FD_ISSET(sock[n].fd, &read_fds)){
if(ws_data(sock + n)){
break;
}
}
if(sock[n].peer >= 0 && FD_ISSET(sock[n].peer, &read_fds)){
if(ws_peer_data(sock + n)){
break;
}
}
}
}
}
}
//cleanup
ws_cleanup();
close(listen_fd);
return 0;
}
|