@@ -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
504504int 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 ];
0 commit comments