Skip to content

Commit 0ae2219

Browse files
committed
bug fixes. begin support for > 65535 byte payloads. clean-up
1 parent f18ec23 commit 0ae2219

File tree

717 files changed

+5735
-5648
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

717 files changed

+5735
-5648
lines changed

src/cwebsocket/client.c

Lines changed: 76 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ void cwebsocket_client_init(cwebsocket_client *websocket, cwebsocket_subprotocol
3333
websocket->subprotocol_len = subprotocol_len;
3434
int i;
3535
for(i=0; i<subprotocol_len; i++) {
36-
syslog(LOG_DEBUG, "cwebsocket_client_init: initializing subprotocol %s", subprotocols[i]->name);
36+
syslog(LOG_DEBUG, "cwebsocket_client_init: loading subprotocol %s", subprotocols[i]->name);
3737
websocket->subprotocols[i] = subprotocols[i];
3838
}
3939
const rlim_t kStackSize = CWS_STACK_SIZE_MIN * 1024 * 1024;
@@ -221,7 +221,6 @@ int cwebsocket_client_connect(cwebsocket_client *websocket) {
221221
}
222222

223223
if(connect(websocket->fd, servinfo->ai_addr, servinfo->ai_addrlen) != 0 ) {
224-
freeaddrinfo(servinfo);
225224
syslog(LOG_ERR, "cwebsocket_client_connect: %s", strerror(errno));
226225
cwebsocket_client_onerror(websocket, strerror(errno));
227226
websocket->state = WEBSOCKET_STATE_CLOSED;
@@ -231,7 +230,6 @@ int cwebsocket_client_connect(cwebsocket_client *websocket) {
231230
}
232231
return -1;
233232
}
234-
235233
freeaddrinfo(servinfo);
236234

237235
int optval = 1;
@@ -445,6 +443,7 @@ int cwebsocket_client_send_control_frame(cwebsocket_client *websocket, opcode co
445443
int header_len = 6;
446444
int frame_len = header_len + payload_len;
447445
uint8_t control_frame[frame_len];
446+
memset(control_frame, 0, frame_len);
448447
uint8_t masking_key[4];
449448
cwebsocket_client_create_masking_key(masking_key);
450449
control_frame[0] = (code | 0x80);
@@ -462,6 +461,7 @@ int cwebsocket_client_send_control_frame(cwebsocket_client *websocket, opcode co
462461
if(payload_len > 2) {
463462
char parsed_payload[payload_len-2];
464463
memcpy(parsed_payload, &payload[2], payload_len-2);
464+
parsed_payload[payload_len-2] = '\0';
465465
int i;
466466
for(i=0; i<payload_len; i++) {
467467
control_frame[8+i] = (parsed_payload[i] ^ masking_key[i % 4]) & 0xff;
@@ -503,32 +503,33 @@ int cwebsocket_client_send_control_frame(cwebsocket_client *websocket, opcode co
503503

504504
int cwebsocket_client_read_data(cwebsocket_client *websocket) {
505505

506-
ssize_t byte = 0;
507-
int header_length = 2; // The size of the header (header = everything up until the start of the payload)
508-
const int header_length_offset = 2; // The byte which starts the 2 byte header
509-
const int extended_payload16_end_byte = 4; // The byte which completes the extended 16-bit payload length bits
510-
const int extended_payload64_end_byte = 10; // The byte which completes the extended 64-bit payload length bits
511-
int bytes_read = 0; // Current byte counter
512-
int payload_length = 0; // Total length of the payload/data (minus the variable length header)
513-
int extended_payload_length; // Stores the extended payload length bits, if present
514-
uint8_t data[CWS_DATA_BUFFER_MAX] = {0}; // Data stream buffer
515-
cwebsocket_frame frame; // WebSocket Data Frame - RFC 6455 Section 5.2
516-
memset(&frame, 0, sizeof(frame));
506+
int header_length = 2, bytes_read = 0;
507+
const int header_length_offset = 2;
508+
const int extended_payload16_end_byte = 4;
509+
const int extended_payload64_end_byte = 10;
510+
uint64_t payload_length = 0;
517511

518-
while(bytes_read < header_length + payload_length) {
512+
uint8_t *data = malloc(CWS_DATA_BUFFER_MAX);
513+
if(data == NULL) {
514+
perror("out of memory");
515+
exit(-1);
516+
}
517+
memset(data, 0, CWS_DATA_BUFFER_MAX);
519518

520-
if((websocket->state & WEBSOCKET_STATE_OPEN) == 0) {
521-
return -1;
522-
}
519+
cwebsocket_frame frame;
520+
memset(&frame, 0, sizeof(frame));
521+
522+
uint64_t frame_size = header_length;
523+
while(bytes_read < frame_size && (websocket->state & WEBSOCKET_STATE_OPEN)) {
523524

524-
if(bytes_read == CWS_DATA_BUFFER_MAX) {
525+
if(bytes_read >= CWS_DATA_BUFFER_MAX) {
525526
syslog(LOG_ERR, "cwebsocket_client_read_data: frame too large. RECEIVE_BUFFER_MAX = %i bytes. bytes_read=%i, header_length=%i",
526527
CWS_DATA_BUFFER_MAX, bytes_read, header_length);
527528
cwebsocket_client_close(websocket, 1009, "frame too large");
528529
return -1;
529530
}
530531

531-
byte = cwebsocket_client_read(websocket, data+bytes_read, 1);
532+
ssize_t byte = cwebsocket_client_read(websocket, data+bytes_read, 1);
532533

533534
if(byte == 0) {
534535
char *errmsg = "server closed the connection";
@@ -549,7 +550,7 @@ int cwebsocket_client_read_data(cwebsocket_client *websocket) {
549550
frame.rsv1 = (data[0] & 0x40) == 0x40 ? 1 : 0;
550551
frame.rsv2 = (data[0] & 0x20) == 0x20 ? 1 : 0;
551552
frame.rsv3 = (data[0] & 0x10) == 0x10 ? 1 : 0;
552-
frame.opcode = (data[0] & 0x7F);// ((data[0] & 0x08) | (data[0] & 0x04) | (data[0] & 0x02) | (data[0] & 0x01));
553+
frame.opcode = (data[0] & 0x7F);
553554
frame.mask = data[1] & 0x80;
554555
frame.payload_len = (data[1] & 0x7F);
555556

@@ -560,22 +561,26 @@ int cwebsocket_client_read_data(cwebsocket_client *websocket) {
560561
return -1;
561562
}
562563

563-
header_length = 2 + (frame.payload_len == 126 ? 2 : 0) + (frame.payload_len == 127 ? 6 : 0);
564564
payload_length = frame.payload_len;
565-
extended_payload_length = 0;
565+
frame_size = header_length + payload_length;
566566
}
567567

568568
if(frame.payload_len == 126 && bytes_read == extended_payload16_end_byte) {
569569

570-
extended_payload_length = 0;
570+
header_length += 2;
571+
572+
uint16_t extended_payload_length = 0;
571573
extended_payload_length |= ((uint8_t) data[2]) << 8;
572574
extended_payload_length |= ((uint8_t) data[3]) << 0;
573575

574576
payload_length = extended_payload_length;
577+
frame_size = header_length + payload_length;
575578
}
576579
else if(frame.payload_len == 127 && bytes_read == extended_payload64_end_byte) {
577580

578-
extended_payload_length = 0;
581+
header_length += 6;
582+
583+
uint64_t extended_payload_length = 0;
579584
extended_payload_length |= ((uint64_t) data[2]) << 56;
580585
extended_payload_length |= ((uint64_t) data[3]) << 48;
581586
extended_payload_length |= ((uint64_t) data[4]) << 40;
@@ -586,35 +591,54 @@ int cwebsocket_client_read_data(cwebsocket_client *websocket) {
586591
extended_payload_length |= ((uint64_t) data[9]) << 0;
587592

588593
payload_length = extended_payload_length;
594+
frame_size = header_length + payload_length;
589595
}
590596
}
591597

592598
if(frame.fin && frame.opcode == TEXT_FRAME) {
593599

594-
uint8_t payload[payload_length];
595-
memcpy(payload, &data[header_length], payload_length * sizeof(uint8_t));
600+
char *payload = malloc(sizeof(char) * payload_length);
601+
if(payload == NULL) {
602+
perror("out of memory");
603+
exit(-1);
604+
}
605+
memcpy(payload, &data[header_length], payload_length);
596606
payload[payload_length] = '\0';
607+
free(data);
597608

598609
size_t utf8_code_points = 0;
599-
if(utf8_count_code_points(payload, &utf8_code_points)) {
600-
syslog(LOG_ERR, "cwebsocket_client_read_data: received %i byte malformed utf8 text payload: %s", payload_length, payload);
610+
if(utf8_count_code_points((uint8_t *)payload, &utf8_code_points)) {
611+
syslog(LOG_ERR, "cwebsocket_client_read_data: received %zu byte malformed utf8 text payload: %s", payload_length, payload);
601612
cwebsocket_client_onerror(websocket, "received malformed utf8 payload");
602613
return -1;
603614
}
604615

605-
syslog(LOG_DEBUG, "cwebsocket_client_read_data: received %i byte text payload: %s", payload_length, payload);
616+
syslog(LOG_DEBUG, "cwebsocket_client_read_data: received %zu byte text payload: %s", payload_length, payload);
606617

607618
if(websocket->subprotocol != NULL && websocket->subprotocol->onmessage != NULL) {
608619

609620
#ifdef THREADED
610621
cwebsocket_message *message = malloc(sizeof(cwebsocket_message));
622+
if(message == NULL) {
623+
perror("out of memory");
624+
exit(-1);
625+
}
611626
memset(message, 0, sizeof(cwebsocket_message));
612627
message->opcode = frame.opcode;
613628
message->payload_len = frame.payload_len;
614-
message->payload = malloc(payload_length+1);
615-
strncpy(message->payload, (char *)payload, payload_length+1);
629+
message->payload = malloc(sizeof(char) * (payload_length+1));
630+
if(message->payload == NULL) {
631+
perror("out of memory");
632+
exit(-1);
633+
}
634+
strncpy(message->payload, payload, payload_length+1);
635+
free(payload);
616636

617637
cwebsocket_client_thread_args *args = malloc(sizeof(cwebsocket_thread_args));
638+
if(args == NULL) {
639+
perror("out of memory");
640+
exit(-1);
641+
}
618642
memset(args, 0, sizeof(cwebsocket_thread_args));
619643
args->socket = websocket;
620644
args->message = message;
@@ -629,8 +653,15 @@ int cwebsocket_client_read_data(cwebsocket_client *websocket) {
629653
cwebsocket_message message = {0};
630654
message.opcode = frame.opcode;
631655
message.payload_len = frame.payload_len;
632-
message.payload = (char *)payload;
656+
message.payload = malloc(sizeof(char) * (payload_length+1));
657+
if(message.payload == NULL) {
658+
perror("out of memory");
659+
exit(-1);
660+
}
661+
strncpy(message.payload, payload, payload_length+1);
633662
cwebsocket_client_onmessage(websocket, &message);
663+
free(payload);
664+
free(message.payload);
634665
return bytes_read;
635666
#endif
636667
}
@@ -640,10 +671,11 @@ int cwebsocket_client_read_data(cwebsocket_client *websocket) {
640671
}
641672
else if(frame.fin && frame.opcode == BINARY_FRAME) {
642673

643-
syslog(LOG_DEBUG, "cwebsocket_client_read_data: received BINARY payload. bytes=%i", payload_length);
674+
syslog(LOG_DEBUG, "cwebsocket_client_read_data: received BINARY payload. bytes=%zu", payload_length);
644675

645676
char payload[payload_length];
646677
memcpy(payload, &data[header_length], payload_length);
678+
free(data);
647679

648680
if(websocket->subprotocol->onmessage != NULL) {
649681

@@ -689,6 +721,7 @@ int cwebsocket_client_read_data(cwebsocket_client *websocket) {
689721
uint8_t payload[payload_length];
690722
memcpy(payload, &data[header_length], payload_length);
691723
payload[payload_length] = '\0';
724+
free(data);
692725
return cwebsocket_client_send_control_frame(websocket, 0x0A, "PONG", payload, payload_length);
693726
}
694727
else if(frame.opcode == PONG) {
@@ -709,11 +742,13 @@ int cwebsocket_client_read_data(cwebsocket_client *websocket) {
709742
uint8_t payload[payload_length];
710743
memcpy(payload, &data[header_length], (payload_length) * sizeof(uint8_t));
711744
payload[payload_length] = '\0';
712-
syslog(LOG_DEBUG, "cwebsocket_client_read_data: received CLOSE control frame. bytes=%i, code=%i, reason=%s", payload_length, code, payload);
745+
free(data);
746+
syslog(LOG_DEBUG, "cwebsocket_client_read_data: received CLOSE control frame. payload_length=%zu, code=%i, reason=%s", payload_length, code, payload);
713747
cwebsocket_client_close(websocket, code, NULL);
714748
return 0;
715749
}
716750

751+
free(data);
717752
char closemsg[50];
718753
sprintf(closemsg, "received unsupported opcode: %#04x", frame.opcode);
719754
syslog(LOG_ERR, "cwebsocket_client_read_data: %s", closemsg);
@@ -749,13 +784,15 @@ ssize_t cwebsocket_client_write_data(cwebsocket_client *websocket, const char *d
749784
header[0] = (code | 0x80);
750785

751786
if(payload_len <= 125) {
787+
752788
header[1] = (payload_len | 0x80);
753789
header[2] = masking_key[0];
754790
header[3] = masking_key[1];
755791
header[4] = masking_key[2];
756792
header[5] = masking_key[3];
757793
}
758-
else if(payload_len > 125 && payload_len <= 0xffff) {
794+
else if(payload_len > 125 && payload_len <= 0xffff) { // 125 && 65535
795+
759796
uint16_t len16 = htons(payload_len);
760797
header[1] = (126 | 0x80);
761798
memcpy(header+2, &len16, 2);
@@ -764,10 +801,11 @@ ssize_t cwebsocket_client_write_data(cwebsocket_client *websocket, const char *d
764801
header[6] = masking_key[2];
765802
header[7] = masking_key[3];
766803
}
767-
else if(payload_len > 0xffff && payload_len <= 0xffffffffffffffffLL) {
804+
else if(payload_len > 0xffff && payload_len <= 0xffffffffffffffffLL) { // 65535 && 18446744073709551615
805+
768806
char len64[8] = htonl64(payload_len);
769807
header[1] = (127 | 0x80);
770-
memcpy(header+2, &len64, 8);
808+
memcpy(header+2, len64, 8);
771809
header[10] = masking_key[0];
772810
header[11] = masking_key[1];
773811
header[12] = masking_key[2];

src/cwebsocket/common.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ char* cwebsocket_base64_encode(const unsigned char *input, int length) {
4141
}
4242

4343
void cwebsocket_print_frame(cwebsocket_frame *frame) {
44-
syslog(LOG_DEBUG, "cwebsocket_print_frame: fin=%i, rsv1=%i, rsv2=%i, rsv3=%i, opcode=%#04x, mask=%i, payload_len=%i\n",
44+
syslog(LOG_DEBUG, "cwebsocket_print_frame: fin=%i, rsv1=%i, rsv2=%i, rsv3=%i, opcode=%#04x, mask=%i, payload_len=%zu\n",
4545
frame->fin, frame->rsv1, frame->rsv2, frame->rsv3, frame->opcode, frame->mask, frame->payload_len);
4646
}
4747

src/cwebsocket/common.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
#include <openssl/buffer.h>
4646
#include "utf8.h"
4747

48+
#include <limits.h>
49+
4850
#ifdef USESSL
4951
#include <openssl/rand.h>
5052
#include <openssl/ssl.h>
@@ -120,7 +122,7 @@ typedef struct {
120122
bool rsv3;
121123
opcode opcode;
122124
bool mask;
123-
int payload_len;
125+
uint64_t payload_len;
124126
uint32_t masking_key[4];
125127
} cwebsocket_frame;
126128

0 commit comments

Comments
 (0)