Skip to content

Commit e142e89

Browse files
committed
merge with websocket commit
1 parent 6aea004 commit e142e89

File tree

3 files changed

+104
-84
lines changed

3 files changed

+104
-84
lines changed

include/net/websocket.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ int websocket_send_msg(int ws_sock, const u8_t *payload, size_t payload_len,
124124
*/
125125
int websocket_recv_msg(int ws_sock, u8_t *buf, size_t buf_len,
126126
bool *masked, u32_t *mask_value, u32_t *message_type,
127-
s32_t timeout);
127+
u64_t *message_len, s32_t timeout);
128128

129129
/**
130130
*/

subsys/net/lib/websocket/websocket.c

Lines changed: 81 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ LOG_MODULE_REGISTER(net_websocket, CONFIG_NET_WEBSOCKET_LOG_LEVEL);
1818
#include <errno.h>
1919
#include <stdbool.h>
2020
#include <stdlib.h>
21+
#include <sys/byteorder.h>
2122

2223
#include <sys/fdtable.h>
24+
#include <net/net_core.h>
2325
#include <net/net_ip.h>
2426
#include <net/socket.h>
2527
#include <net/http_client.h>
@@ -437,7 +439,7 @@ int websocket_send_msg(int ws_sock, const u8_t *payload, size_t payload_len,
437439
s32_t timeout)
438440
{
439441
struct websocket_context *ctx;
440-
u8_t header[14], hdr_len = 2;
442+
u8_t header[MAX_HEADER_LEN], hdr_len = 2;
441443
u8_t *data_to_send = (u8_t *)payload;
442444
int ret;
443445

@@ -525,65 +527,34 @@ int websocket_send_msg(int ws_sock, const u8_t *payload, size_t payload_len,
525527
return ret;
526528
}
527529

528-
#if 0
529-
static void websocket_mask_pkt(struct net_pkt *pkt, u32_t masking_value,
530-
u32_t *data_read)
531-
{
532-
struct net_buf *frag;
533-
u16_t pos;
534-
int i;
535-
536-
frag = net_frag_get_pos(pkt,
537-
net_pkt_get_len(pkt) - net_pkt_appdatalen(pkt),
538-
&pos);
539-
if (!frag) {
540-
return;
541-
}
542-
543-
NET_ASSERT(net_pkt_appdata(pkt) == frag->data + pos);
544-
545-
while (frag) {
546-
for (i = pos; i < frag->len; i++, (*data_read)++) {
547-
frag->data[i] ^=
548-
masking_value >> (8 * (3 - (*data_read) % 4));
549-
}
550-
551-
pos = 0;
552-
frag = frag->frags;
553-
}
554-
}
555-
#endif
556-
557-
static int websocket_strip_header(u8_t *buf, size_t buf_len, bool *masked,
558-
u32_t *mask_value, size_t *message_length,
559-
u32_t *message_type_flag, size_t *header_len)
530+
static void websocket_parse_header(u8_t *buf, size_t buf_len, bool *masked,
531+
u32_t *mask_value, u64_t *message_length,
532+
u32_t *message_type_flag, size_t *header_len)
560533
{
561-
#if 0
562-
size_t read_pos = 0;
563-
u16_t value;
564-
u8_t len; /* message length byte */
565534
u8_t len_len; /* length of the length field in header */
535+
u8_t len; /* message length byte */
536+
u16_t value;
566537

567538
value = sys_get_be16(&buf[0]);
568539
if (value & 0x8000) {
569-
*message_type_flag |= WS_FLAG_FINAL;
540+
*message_type_flag |= WEBSOCKET_FLAG_FINAL;
570541
}
571542

572543
switch (value & 0x0f00) {
573544
case 0x0100:
574-
*message_type_flag |= WS_FLAG_TEXT;
545+
*message_type_flag |= WEBSOCKET_FLAG_TEXT;
575546
break;
576547
case 0x0200:
577-
*message_type_flag |= WS_FLAG_BINARY;
548+
*message_type_flag |= WEBSOCKET_FLAG_BINARY;
578549
break;
579550
case 0x0800:
580-
*message_type_flag |= WS_FLAG_CLOSE;
551+
*message_type_flag |= WEBSOCKET_FLAG_CLOSE;
581552
break;
582553
case 0x0900:
583-
*message_type_flag |= WS_FLAG_PING;
554+
*message_type_flag |= WEBSOCKET_FLAG_PING;
584555
break;
585556
case 0x0A00:
586-
*message_type_flag |= WS_FLAG_PONG;
557+
*message_type_flag |= WEBSOCKET_FLAG_PONG;
587558
break;
588559
}
589560

@@ -592,57 +563,32 @@ static int websocket_strip_header(u8_t *buf, size_t buf_len, bool *masked,
592563
len_len = 0;
593564
*message_length = len;
594565
} else if (len == 126) {
595-
u16_t msg_len;
596-
597566
len_len = 2;
598-
599-
frag = net_frag_read_be16(frag, pos, &pos, &msg_len);
600-
if (!frag && pos == 0xffff) {
601-
return -ENOMSG;
602-
}
603-
604-
*message_length = msg_len;
567+
*message_length = sys_get_be16(&buf[2]);
605568
} else {
606-
len_len = 4;
607-
608-
frag = net_frag_read_be32(frag, pos, &pos, message_length);
609-
if (!frag && pos == 0xffff) {
610-
return -ENOMSG;
611-
}
569+
len_len = 8;
570+
*message_length = sys_get_be64(&buf[2]);
612571
}
613572

614573
if (value & 0x0080) {
615574
*masked = true;
616-
appdata_pos = 0;
617-
618-
frag = net_frag_read_be32(frag, pos, &pos, mask_value);
619-
if (!frag && pos == 0xffff) {
620-
return -ENOMSG;
621-
}
575+
*mask_value = sys_get_be32(&buf[2 + len_len]);
622576
} else {
623577
*masked = false;
624-
appdata_pos = len_len;
625-
}
626-
627-
frag = net_frag_get_pos(pkt, pos + appdata_pos, &pos);
628-
if (!frag && pos == 0xffff) {
629-
return -ENOMSG;
630578
}
631579

632580
/* Minimum websocket header is 6 bytes, header length might be
633581
* bigger depending on length field len.
634582
*/
635583
*header_len = 6 + len_len;
636-
#endif
637-
return 0;
638584
}
639585

640586
int websocket_recv_msg(int ws_sock, u8_t *buf, size_t buf_len,
641587
bool *masked, u32_t *mask_value, u32_t *message_type,
642-
s32_t timeout)
588+
u64_t *message_len, s32_t timeout)
643589
{
644590
struct websocket_context *ctx;
645-
size_t message_length, header_len;
591+
size_t header_len, pos_to_write = 0;
646592
u32_t message_type_flag;
647593
int ret;
648594

@@ -655,20 +601,71 @@ int websocket_recv_msg(int ws_sock, u8_t *buf, size_t buf_len,
655601
return -ENOENT;
656602
}
657603

658-
ret = recv(ctx->real_sock, buf, buf_len,
604+
if (!ctx->header_received) {
605+
ret = recv(ctx->real_sock, &ctx->header[ctx->pos],
606+
sizeof(ctx->header) - ctx->pos,
607+
timeout == K_NO_WAIT ? MSG_DONTWAIT : 0);
608+
if (ret < 0) {
609+
return ret;
610+
}
611+
612+
if (ret < sizeof(ctx->header)) {
613+
ctx->pos += ret;
614+
return -EAGAIN;
615+
}
616+
617+
/* All the header is now received, we can read the data next */
618+
ctx->header_received = true;
619+
620+
websocket_parse_header(ctx->header, ret, masked, mask_value,
621+
message_len, &message_type_flag,
622+
&header_len);
623+
624+
/* If there is any data in the header, then move it to the
625+
* data buffer.
626+
*/
627+
if (header_len < sizeof(ctx->header)) {
628+
NET_ASSERT(ctx->pos <= sizeof(ctx->header));
629+
630+
memcpy(buf, &ctx->header[header_len],
631+
sizeof(ctx->header) - ctx->pos);
632+
pos_to_write = sizeof(ctx->header) - ctx->pos;
633+
}
634+
635+
ctx->message_len = *message_len;
636+
}
637+
638+
ret = recv(ctx->real_sock, &buf[pos_to_write],
639+
buf_len - pos_to_write,
659640
timeout == K_NO_WAIT ? MSG_DONTWAIT : 0);
660641
if (ret < 0) {
661642
return ret;
662643
}
663644

664-
ret = websocket_strip_header(buf, buf_len, masked, mask_value,
665-
&message_length, &message_type_flag,
666-
&header_len);
667-
if (ret < 0) {
668-
return ret;
645+
ret += pos_to_write;
646+
647+
/* Unmask the data */
648+
websocket_mask_payload(buf, ret, *mask_value);
649+
650+
ctx->total_read += ret;
651+
652+
/* If we receive the end of the message and there is still data left,
653+
* store the remaining to header and tmp buffer.
654+
*/
655+
if (ctx->total_read >= ctx->message_len) {
656+
ret -= ctx->total_read - ctx->message_len;
657+
658+
if (ret > 0) {
659+
/* Rest of the stuff is suppose to go to header temp
660+
* buffer and to user specified temp buf
661+
*/
662+
663+
} else {
664+
ctx->header_received = false;
665+
}
669666
}
670667

671-
return 0;
668+
return ret;
672669
}
673670

674671
static int websocket_send(struct websocket_context *ctx, const u8_t *buf,
@@ -688,11 +685,13 @@ static int websocket_recv(struct websocket_context *ctx, u8_t *buf,
688685
bool masked;
689686
u32_t mask_value;
690687
u32_t message_type;
688+
u64_t message_len;
691689

692690
NET_DBG("[%p] Waiting data, buf len %zd bytes", ctx, buf_len);
693691

694692
return websocket_recv_msg(ctx->sock, buf, buf_len, &masked,
695-
&mask_value, &message_type, timeout);
693+
&mask_value, &message_type, &message_len,
694+
timeout);
696695
}
697696

698697
static ssize_t websocket_read_vmeth(void *obj, void *buffer, size_t count)

subsys/net/lib/websocket/websocket_internal.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212

1313
#define WS_SHA1_OUTPUT_LEN 20
1414

15+
/* Max Websocket header length */
16+
#define MAX_HEADER_LEN 14
17+
1518
/* From RFC 6455 chapter 4.2.2 */
1619
#define WS_MAGIC "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
1720

@@ -52,7 +55,7 @@ struct websocket_context {
5255
};
5356

5457
/** Temporary buffers used for HTTP handshakes and Websocket protocol
55-
* headers.
58+
* headers. User must provide the buffer pointer.
5659
*/
5760
u8_t *tmp_buf;
5861

@@ -71,6 +74,21 @@ struct websocket_context {
7174
*/
7275
s32_t timeout;
7376

77+
/** Internal buffer for Websocket header when reading data. Shared
78+
* with the amount of data received.
79+
*/
80+
union {
81+
struct {
82+
u8_t header[MAX_HEADER_LEN];
83+
u8_t pos;
84+
};
85+
86+
struct {
87+
u64_t total_read;
88+
u64_t message_len;
89+
};
90+
};
91+
7492
/** Did we receive Sec-WebSocket-Accept: field */
7593
u8_t sec_accept_present:1;
7694

@@ -79,6 +97,9 @@ struct websocket_context {
7997

8098
/** Did we receive all from peer during HTTP handshake */
8199
u8_t all_received:1;
100+
101+
/** Header received */
102+
u8_t header_received:1;
82103
};
83104

84105
#if 0

0 commit comments

Comments
 (0)