Add the ability to handle the binary protocol
This commit is contained in:
parent
63600bf422
commit
4909486139
|
|
@ -268,33 +268,43 @@ int decode_hixie(char *src, size_t srclength,
|
|||
int encode_hybi(u_char const *src, size_t srclength,
|
||||
char *target, size_t targsize, unsigned int opcode)
|
||||
{
|
||||
unsigned long long b64_sz, len_offset = 1, payload_offset = 2, len = 0;
|
||||
unsigned long long pay_sz, len_offset = 1, payload_offset = 2, len = 0;
|
||||
|
||||
if ((int)srclength <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
b64_sz = ((srclength - 1) / 3) * 4 + 4;
|
||||
if (opcode == 1)
|
||||
pay_sz = ((srclength - 1) / 3) * 4 + 4;
|
||||
if (opcode == 2)
|
||||
pay_sz = srclength;
|
||||
|
||||
target[0] = (char)(opcode & 0x0F | 0x80);
|
||||
|
||||
if (b64_sz <= 125) {
|
||||
target[1] = (char) b64_sz;
|
||||
if (pay_sz <= 125) {
|
||||
target[1] = (char) pay_sz;
|
||||
payload_offset = 2;
|
||||
} else if ((b64_sz > 125) && (b64_sz < 65536)) {
|
||||
} else if ((pay_sz > 125) && (pay_sz < 65536)) {
|
||||
target[1] = (char) 126;
|
||||
*(u_short*)&(target[2]) = htons(b64_sz);
|
||||
*(u_short*)&(target[2]) = htons(pay_sz);
|
||||
payload_offset = 4;
|
||||
} else {
|
||||
handler_emsg("Sending frames larger than 65535 bytes not supported\n");
|
||||
return -1;
|
||||
//target[1] = (char) 127;
|
||||
//*(u_long*)&(target[2]) = htonl(b64_sz);
|
||||
//*(u_long*)&(target[2]) = htonl(pay_sz);
|
||||
//payload_offset = 10;
|
||||
}
|
||||
|
||||
len = b64_ntop(src, srclength, target+payload_offset, targsize-payload_offset);
|
||||
if (opcode == 1) {
|
||||
len = b64_ntop(src, srclength, target+payload_offset, targsize-payload_offset);
|
||||
}
|
||||
|
||||
if (opcode == 2) {
|
||||
len = srclength;
|
||||
memcpy(target + payload_offset, src, len);
|
||||
}
|
||||
|
||||
if (len < 0) {
|
||||
return len;
|
||||
|
|
@ -316,7 +326,7 @@ int decode_hybi(unsigned char *src, size_t srclength,
|
|||
*left = srclength;
|
||||
frame = src;
|
||||
|
||||
//printf("Deocde new frame\n");
|
||||
//printf("Decode new frame\n");
|
||||
while (1) {
|
||||
// Need at least two bytes of the header
|
||||
// Find beginning of next frame. First time hdr_length, masked and
|
||||
|
|
@ -379,9 +389,11 @@ int decode_hybi(unsigned char *src, size_t srclength,
|
|||
return -1;
|
||||
}
|
||||
|
||||
// Terminate with a null for base64 decode
|
||||
save_char = payload[payload_length];
|
||||
payload[payload_length] = '\0';
|
||||
if (*opcode == 1) {
|
||||
// Terminate with a null for base64 decode
|
||||
save_char = payload[payload_length];
|
||||
payload[payload_length] = '\0';
|
||||
}
|
||||
|
||||
// unmask the data
|
||||
mask = payload - 4;
|
||||
|
|
@ -389,15 +401,23 @@ int decode_hybi(unsigned char *src, size_t srclength,
|
|||
payload[i] ^= mask[i%4];
|
||||
}
|
||||
|
||||
// base64 decode the data
|
||||
len = b64_pton((const char*)payload, target+target_offset, targsize);
|
||||
if (*opcode == 1) {
|
||||
// base64 decode the data
|
||||
len = b64_pton((const char*)payload, target+target_offset, targsize);
|
||||
|
||||
// Restore the first character of the next frame
|
||||
payload[payload_length] = save_char;
|
||||
if (len < 0) {
|
||||
handler_emsg("Base64 decode error code %d", len);
|
||||
return len;
|
||||
// Restore the first character of the next frame
|
||||
payload[payload_length] = save_char;
|
||||
if (len < 0) {
|
||||
handler_emsg("Base64 decode error code %d", len);
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
if (*opcode == 2) {
|
||||
len = payload_length;
|
||||
memcpy(target + target_offset, payload, len);
|
||||
}
|
||||
|
||||
target_offset += len;
|
||||
|
||||
//printf(" len %d, raw %s\n", len, frame);
|
||||
|
|
@ -409,6 +429,7 @@ int decode_hybi(unsigned char *src, size_t srclength,
|
|||
}
|
||||
|
||||
*left = remaining;
|
||||
//printf(" returning %d, %d left\n", target_offset, *left);
|
||||
return target_offset;
|
||||
}
|
||||
|
||||
|
|
@ -481,6 +502,10 @@ int parse_handshake(ws_ctx_t *ws_ctx, char *handshake) {
|
|||
end = strstr(start, "\r\n");
|
||||
strncpy(headers->protocols, start, end-start);
|
||||
headers->protocols[end-start] = '\0';
|
||||
if (strstr(headers->protocols, "binary"))
|
||||
ws_ctx->binary = 1;
|
||||
else
|
||||
ws_ctx->binary = 0;
|
||||
} else {
|
||||
// Hixie 75 or 76
|
||||
ws_ctx->hybi = 0;
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ typedef struct {
|
|||
SSL *ssl;
|
||||
int hixie;
|
||||
int hybi;
|
||||
int binary;
|
||||
headers_t *headers;
|
||||
char *cin_buf;
|
||||
char *cout_buf;
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
|
|||
if (FD_ISSET(target, &wlist)) {
|
||||
len = tout_end-tout_start;
|
||||
bytes = send(target, ws_ctx->tout_buf + tout_start, len, 0);
|
||||
//printf("wrote %d bytes of an intended %d bytes\n", bytes, len);
|
||||
if (pipe_error) { break; }
|
||||
if (bytes < 0) {
|
||||
handler_emsg("target connection error: %s\n",
|
||||
|
|
@ -149,29 +150,42 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
|
|||
bytes = recv(target, ws_ctx->cin_buf, DBUFSIZE , 0);
|
||||
if (pipe_error) { break; }
|
||||
if (bytes <= 0) {
|
||||
unsigned char term_buf[48];
|
||||
unsigned char term_rc[2] = {0x0,0};
|
||||
|
||||
handler_emsg("target closed connection\n");
|
||||
|
||||
bytes = encode_hybi(term_rc, 2, term_buf, sizeof(term_buf), 2);
|
||||
term_buf[0] |= 8;
|
||||
send(ws_ctx->sockfd, term_buf, bytes, 0);
|
||||
shutdown(ws_ctx->sockfd, SHUT_WR);
|
||||
close(target);
|
||||
close(ws_ctx->sockfd);
|
||||
break;
|
||||
}
|
||||
cout_start = 0;
|
||||
if (ws_ctx->hybi) {
|
||||
cout_end = encode_hybi(ws_ctx->cin_buf, bytes,
|
||||
ws_ctx->cout_buf, BUFSIZE, 1);
|
||||
} else {
|
||||
cout_end = encode_hixie(ws_ctx->cin_buf, bytes,
|
||||
ws_ctx->cout_buf, BUFSIZE);
|
||||
|
||||
else {
|
||||
cout_start = 0;
|
||||
if (ws_ctx->hybi) {
|
||||
cout_end = encode_hybi(ws_ctx->cin_buf, bytes,
|
||||
ws_ctx->cout_buf, BUFSIZE, ws_ctx->binary ? 2 : 1);
|
||||
} else {
|
||||
cout_end = encode_hixie(ws_ctx->cin_buf, bytes,
|
||||
ws_ctx->cout_buf, BUFSIZE);
|
||||
}
|
||||
/*
|
||||
printf("encoded: ");
|
||||
for (i=0; i< cout_end; i++) {
|
||||
printf("%u,", (unsigned char) *(ws_ctx->cout_buf+i));
|
||||
}
|
||||
printf("\n");
|
||||
*/
|
||||
if (cout_end < 0) {
|
||||
handler_emsg("encoding error\n");
|
||||
break;
|
||||
}
|
||||
traffic("{");
|
||||
}
|
||||
/*
|
||||
printf("encoded: ");
|
||||
for (i=0; i< cout_end; i++) {
|
||||
printf("%u,", (unsigned char) *(ws_ctx->cout_buf+i));
|
||||
}
|
||||
printf("\n");
|
||||
*/
|
||||
if (cout_end < 0) {
|
||||
handler_emsg("encoding error\n");
|
||||
break;
|
||||
}
|
||||
traffic("{");
|
||||
}
|
||||
|
||||
if (FD_ISSET(client, &rlist)) {
|
||||
|
|
@ -181,6 +195,7 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
|
|||
handler_emsg("client closed connection\n");
|
||||
break;
|
||||
}
|
||||
|
||||
tin_end += bytes;
|
||||
/*
|
||||
printf("before decode: ");
|
||||
|
|
@ -206,13 +221,6 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
|
|||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
printf("decoded: ");
|
||||
for (i=0; i< len; i++) {
|
||||
printf("%u,", (unsigned char) *(ws_ctx->tout_buf+i));
|
||||
}
|
||||
printf("\n");
|
||||
*/
|
||||
if (len < 0) {
|
||||
handler_emsg("decoding error\n");
|
||||
break;
|
||||
|
|
|
|||
Loading…
Reference in New Issue