This commit is contained in:
Stephen English 2017-04-23 13:57:54 +00:00 committed by GitHub
commit 8de1f97f32
3 changed files with 90 additions and 55 deletions

View File

@ -475,12 +475,17 @@ int parse_handshake(ws_ctx_t *ws_ctx, char *handshake) {
strncpy(headers->connection, start, end-start); strncpy(headers->connection, start, end-start);
headers->connection[end-start] = '\0'; headers->connection[end-start] = '\0';
//RFC 6455 11.3.4 - Sec-WebSocket-Protocol MAY appear multiple times
//in a request. Or it may not appear at all.
start = strstr(handshake, "\r\nSec-WebSocket-Protocol: "); start = strstr(handshake, "\r\nSec-WebSocket-Protocol: ");
if (!start) { return 0; } if (start) {
start += 26; start += 26;
end = strstr(start, "\r\n"); end = strstr(start, "\r\n");
strncpy(headers->protocols, start, end-start); strncpy(headers->protocols, start, end-start);
headers->protocols[end-start] = '\0'; headers->protocols[end-start] = '\0';
} else {
headers->protocols[0] = '\0';
}
} else { } else {
// Hixie 75 or 76 // Hixie 75 or 76
ws_ctx->hybi = 0; ws_ctx->hybi = 0;
@ -791,6 +796,13 @@ void start_server() {
break; // Child process exits break; // Child process exits
} else { // parent process } else { // parent process
settings.handler_id += 1; settings.handler_id += 1;
if (settings.one_at_a_time) {
//Block on child process exiting
handler_msg("Waiting for child to finish\n");
wait(pid);
handler_msg("Child finished\n");
}
} }
} }
if (pid == 0) { if (pid == 0) {

View File

@ -62,6 +62,7 @@ typedef struct {
int ssl_only; int ssl_only;
int daemon; int daemon;
int run_once; int run_once;
int one_at_a_time;
} settings_t; } settings_t;
@ -79,6 +80,6 @@ ssize_t ws_send(ws_ctx_t *ctx, const void *buf, size_t len);
fprintf(stream, __VA_ARGS__); \ fprintf(stream, __VA_ARGS__); \
} }
#define handler_msg(...) gen_handler_msg(stdout, __VA_ARGS__); #define handler_msg(...) gen_handler_msg(stderr, __VA_ARGS__);
#define handler_emsg(...) gen_handler_msg(stderr, __VA_ARGS__); #define handler_emsg(...) gen_handler_msg(stderr, __VA_ARGS__);

View File

@ -32,7 +32,7 @@ Traffic Legend:\n\
"; ";
char USAGE[] = "Usage: [options] " \ char USAGE[] = "Usage: [options] " \
"[source_addr:]source_port target_addr:target_port\n\n" \ "[source_addr:]source_port [target_addr:target_port]\n\n" \
" --verbose|-v verbose messages and per frame traffic\n" \ " --verbose|-v verbose messages and per frame traffic\n" \
" --daemon|-D become a daemon (background process)\n" \ " --daemon|-D become a daemon (background process)\n" \
" --cert CERT SSL certificate file\n" \ " --cert CERT SSL certificate file\n" \
@ -44,13 +44,14 @@ char USAGE[] = "Usage: [options] " \
fprintf(stderr, fmt , ## args); \ fprintf(stderr, fmt , ## args); \
exit(1); exit(1);
int target_local;
char target_host[256]; char target_host[256];
int target_port; int target_port;
extern pipe_error; extern pipe_error;
extern settings_t settings; extern settings_t settings;
void do_proxy(ws_ctx_t *ws_ctx, int target) { void do_proxy(ws_ctx_t *ws_ctx, int target_read, int target_write) {
fd_set rlist, wlist, elist; fd_set rlist, wlist, elist;
struct timeval tv; struct timeval tv;
int i, maxfd, client = ws_ctx->sockfd; int i, maxfd, client = ws_ctx->sockfd;
@ -61,7 +62,8 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
tout_start = tout_end = cout_start = cout_end; tout_start = tout_end = cout_start = cout_end;
tin_start = tin_end = 0; tin_start = tin_end = 0;
maxfd = client > target ? client+1 : target+1; maxfd = client > target_read ? client+1 : target_read+1;
maxfd = maxfd > target_write ? maxfd : target_write+1;
while (1) { while (1) {
tv.tv_sec = 1; tv.tv_sec = 1;
@ -72,18 +74,19 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
FD_ZERO(&elist); FD_ZERO(&elist);
FD_SET(client, &elist); FD_SET(client, &elist);
FD_SET(target, &elist); FD_SET(target_read, &elist);
if( target_write != target_read ) { FD_SET(target_write, &elist); }
if (tout_end == tout_start) { if (tout_end == tout_start) {
// Nothing queued for target, so read from client // Nothing queued for target, so read from client
FD_SET(client, &rlist); FD_SET(client, &rlist);
} else { } else {
// Data queued for target, so write to it // Data queued for target, so write to it
FD_SET(target, &wlist); FD_SET(target_write, &wlist);
} }
if (cout_end == cout_start) { if (cout_end == cout_start) {
// Nothing queued for client, so read from target // Nothing queued for client, so read from target
FD_SET(target, &rlist); FD_SET(target_read, &rlist);
} else { } else {
// Data queued for client, so write to it // Data queued for client, so write to it
FD_SET(client, &wlist); FD_SET(client, &wlist);
@ -92,8 +95,12 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
ret = select(maxfd, &rlist, &wlist, &elist, &tv); ret = select(maxfd, &rlist, &wlist, &elist, &tv);
if (pipe_error) { break; } if (pipe_error) { break; }
if (FD_ISSET(target, &elist)) { if (FD_ISSET(target_read, &elist)) {
handler_emsg("target exception\n"); handler_emsg("target read exception\n");
break;
}
if (FD_ISSET(target_write, &elist)) {
handler_emsg("target write exception\n");
break; break;
} }
if (FD_ISSET(client, &elist)) { if (FD_ISSET(client, &elist)) {
@ -109,9 +116,10 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
continue; continue;
} }
if (FD_ISSET(target, &wlist)) { if (FD_ISSET(target_write, &wlist)) {
len = tout_end-tout_start; len = tout_end-tout_start;
bytes = send(target, ws_ctx->tout_buf + tout_start, len, 0); if( target_local ) { bytes = write(target_write, ws_ctx->tout_buf + tout_start, len); }
else { bytes = send(target_write, ws_ctx->tout_buf + tout_start, len, 0); }
if (pipe_error) { break; } if (pipe_error) { break; }
if (bytes < 0) { if (bytes < 0) {
handler_emsg("target connection error: %s\n", handler_emsg("target connection error: %s\n",
@ -145,8 +153,9 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
} }
} }
if (FD_ISSET(target, &rlist)) { if (FD_ISSET(target_read, &rlist)) {
bytes = recv(target, ws_ctx->cin_buf, DBUFSIZE , 0); if( target_local ) { bytes = read(target_read, ws_ctx->cin_buf, DBUFSIZE); }
else { bytes = recv(target_read, ws_ctx->cin_buf, DBUFSIZE , 0); }
if (pipe_error) { break; } if (pipe_error) { break; }
if (bytes <= 0) { if (bytes <= 0) {
handler_emsg("target closed connection\n"); handler_emsg("target closed connection\n");
@ -236,39 +245,43 @@ void proxy_handler(ws_ctx_t *ws_ctx) {
int tsock = 0; int tsock = 0;
struct sockaddr_in taddr; struct sockaddr_in taddr;
handler_msg("connecting to: %s:%d\n", target_host, target_port); if (target_local) {
do_proxy( ws_ctx, fileno(stdin), fileno(stdout) );
} else {
handler_msg("connecting to: %s:%d\n", target_host, target_port);
tsock = socket(AF_INET, SOCK_STREAM, 0); tsock = socket(AF_INET, SOCK_STREAM, 0);
if (tsock < 0) { if (tsock < 0) {
handler_emsg("Could not create target socket: %s\n", handler_emsg("Could not create target socket: %s\n",
strerror(errno)); strerror(errno));
return; return;
} }
bzero((char *) &taddr, sizeof(taddr)); bzero((char *) &taddr, sizeof(taddr));
taddr.sin_family = AF_INET; taddr.sin_family = AF_INET;
taddr.sin_port = htons(target_port); taddr.sin_port = htons(target_port);
/* Resolve target address */ /* Resolve target address */
if (resolve_host(&taddr.sin_addr, target_host) < -1) { if (resolve_host(&taddr.sin_addr, target_host) < -1) {
handler_emsg("Could not resolve target address: %s\n", handler_emsg("Could not resolve target address: %s\n",
strerror(errno)); strerror(errno));
} }
if (connect(tsock, (struct sockaddr *) &taddr, sizeof(taddr)) < 0) { if (connect(tsock, (struct sockaddr *) &taddr, sizeof(taddr)) < 0) {
handler_emsg("Could not connect to target: %s\n", handler_emsg("Could not connect to target: %s\n",
strerror(errno)); strerror(errno));
close(tsock);
return;
}
if ((settings.verbose) && (! settings.daemon)) {
printf("%s", traffic_legend);
}
do_proxy(ws_ctx, tsock, tsock);
shutdown(tsock, SHUT_RDWR);
close(tsock); close(tsock);
return;
} }
if ((settings.verbose) && (! settings.daemon)) {
printf("%s", traffic_legend);
}
do_proxy(ws_ctx, tsock);
shutdown(tsock, SHUT_RDWR);
close(tsock);
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
@ -336,7 +349,7 @@ int main(int argc, char *argv[])
settings.daemon = daemon; settings.daemon = daemon;
settings.run_once = run_once; settings.run_once = run_once;
if ((argc-optind) != 2) { if((argc-optind) == 0 ) {
usage("Invalid number of arguments\n"); usage("Invalid number of arguments\n");
} }
@ -353,15 +366,24 @@ int main(int argc, char *argv[])
usage("Could not parse listen_port\n"); usage("Could not parse listen_port\n");
} }
found = strstr(argv[optind], ":"); if ((argc-optind) == 1) {
if (found) { //Connect to target on a socket
memcpy(target_host, argv[optind], found-argv[optind]); target_local = 0;
target_port = strtol(found+1, NULL, 10); found = strstr(argv[optind], ":");
if (found) {
memcpy(target_host, argv[optind], found-argv[optind]);
target_port = strtol(found+1, NULL, 10);
} else {
usage("Target argument must be host:port\n");
}
if (target_port == 0) {
usage("Could not parse target port\n");
}
settings.one_at_a_time = 0;
} else { } else {
usage("Target argument must be host:port\n"); //Use normal io for target
} target_local = 1;
if (target_port == 0) { settings.one_at_a_time = 1;
usage("Could not parse target port\n");
} }
if (ssl_only) { if (ssl_only) {