summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Weigel <andreaswe@securepoint.de>2017-02-27 08:45:32 +0100
committerChristian Beier <dontmind@freeshell.org>2017-05-14 20:39:01 +0200
commit5d9d6a87124a5439d3432c37a67f9b2babe04407 (patch)
treed9b78277f3e82d3637efe29c54741a051a4d9bc4
parent8fefdcde2750340c8c4062548e51acc34ae61496 (diff)
downloadlibtdevnc-5d9d6a87.tar.gz
libtdevnc-5d9d6a87.zip
add decode support for continuation frames
use FIN bit and implement opcode 0x00 make consistent use of uint64_t for big frame sizes
-rw-r--r--libvncserver/websockets.c3
-rw-r--r--libvncserver/ws_decode.c137
-rw-r--r--libvncserver/ws_decode.h32
-rwxr-xr-xtest/wsmaketestframe.py15
-rw-r--r--test/wstest.c29
-rw-r--r--test/wstestdata.inc54
6 files changed, 196 insertions, 74 deletions
diff --git a/libvncserver/websockets.c b/libvncserver/websockets.c
index 73ad81c..921015d 100644
--- a/libvncserver/websockets.c
+++ b/libvncserver/websockets.c
@@ -339,12 +339,11 @@ webSocketsHandshake(rfbClientPtr cl, char *scheme)
free(buf);
wsctx = calloc(1, sizeof(ws_ctx_t));
- wsctx->version = WEBSOCKETS_VERSION_HYBI;
wsctx->encode = webSocketsEncodeHybi;
wsctx->decode = webSocketsDecodeHybi;
wsctx->ctxInfo.readFunc = ws_read;
wsctx->base64 = base64;
- hybiDecodeCleanup(wsctx);
+ hybiDecodeCleanupComplete(wsctx);
cl->wsctx = (wsCtx *)wsctx;
return TRUE;
}
diff --git a/libvncserver/ws_decode.c b/libvncserver/ws_decode.c
index 472a44a..485478d 100644
--- a/libvncserver/ws_decode.c
+++ b/libvncserver/ws_decode.c
@@ -8,17 +8,27 @@
#define WS_HYBI_HEADER_LEN_EXTENDED 4 + WS_HYBI_MASK_LEN
#define WS_HYBI_HEADER_LEN_LONG 10 + WS_HYBI_MASK_LEN
-static int
+static inline int
+isControlFrame(ws_ctx_t *wsctx)
+{
+ return 0 != (wsctx->header.opcode & 0x08);
+}
+
+static uint64_t
hybiRemaining(ws_ctx_t *wsctx)
{
return wsctx->nToRead - wsctx->nReadRaw;
}
-void
-hybiDecodeCleanup(ws_ctx_t *wsctx)
+static void
+hybiDecodeCleanupBasics(ws_ctx_t *wsctx)
{
+ /* keep opcode, cleanup rest */
+ wsctx->header.opcode = WS_OPCODE_INVALID;
wsctx->header.payloadLen = 0;
wsctx->header.mask.u = 0;
+ wsctx->header.headerLen = 0;
+ wsctx->header.data = NULL;
wsctx->nReadRaw = 0;
wsctx->nToRead= 0;
wsctx->carrylen = 0;
@@ -26,9 +36,24 @@ hybiDecodeCleanup(ws_ctx_t *wsctx)
wsctx->readlen = 0;
wsctx->hybiDecodeState = WS_HYBI_STATE_HEADER_PENDING;
wsctx->writePos = NULL;
- rfbLog("cleaned up wsctx\n");
}
+static void
+hybiDecodeCleanupForContinuation(ws_ctx_t *wsctx)
+{
+ hybiDecodeCleanupBasics(wsctx);
+ rfbLog("clean up frame, but expect continuation with opcode %d\n", wsctx->continuation_opcode);
+}
+
+void
+hybiDecodeCleanupComplete(ws_ctx_t *wsctx)
+{
+ hybiDecodeCleanupBasics(wsctx);
+ wsctx->continuation_opcode = WS_OPCODE_INVALID;
+ rfbLog("cleaned up wsctx completely\n");
+}
+
+
/**
* Return payload data that has been decoded/unmasked from
* a websocket frame.
@@ -94,10 +119,9 @@ hybiReadHeader(ws_ctx_t *wsctx, int *sockRet, int *nPayload)
{
int ret;
char *headerDst = wsctx->codeBufDecode + wsctx->nReadRaw;
- int n = WSHLENMAX - wsctx->nReadRaw;
+ int n = ((uint64_t)WSHLENMAX) - wsctx->nReadRaw;
rfbLog("header_read to %p with len=%d\n", headerDst, n);
- //ret = ws_read(cl, headerDst, n);
ret = wsctx->ctxInfo.readFunc(wsctx->ctxInfo.ctxPtr, headerDst, n);
rfbLog("read %d bytes from socket\n", ret);
if (ret <= 0) {
@@ -106,29 +130,65 @@ hybiReadHeader(ws_ctx_t *wsctx, int *sockRet, int *nPayload)
int olderrno = errno;
rfbErr("%s: read; %s\n", __func__, strerror(errno));
errno = olderrno;
- *sockRet = -1;
+ goto err_cleanup_state;
} else {
*sockRet = 0;
+ goto err_cleanup_state_sock_closed;
}
- return WS_HYBI_STATE_ERR;
}
wsctx->nReadRaw += ret;
if (wsctx->nReadRaw < 2) {
/* cannot decode header with less than two bytes */
- errno = EAGAIN;
- *sockRet = -1;
- return WS_HYBI_STATE_HEADER_PENDING;
+ goto ret_header_pending;
}
/* first two header bytes received; interpret header data and get rest */
wsctx->header.data = (ws_header_t *)wsctx->codeBufDecode;
wsctx->header.opcode = wsctx->header.data->b0 & 0x0f;
+ wsctx->header.fin = (wsctx->header.data->b0 & 0x80) >> 7;
+ if (isControlFrame(wsctx)) {
+ rfbLog("is control frame\n");
+ /* is a control frame, leave remembered continuation opcode unchanged;
+ * just check if there is a wrong fragmentation */
+ if (wsctx->header.fin == 0) {
+
+ /* we only accept text/binary continuation frames; RFC6455:
+ * Control frames (see Section 5.5) MAY be injected in the middle of
+ * a fragmented message. Control frames themselves MUST NOT be
+ * fragmented. */
+ rfbErr("control frame with FIN bit cleared received, aborting\n");
+ errno = EPROTO;
+ goto err_cleanup_state;
+ }
+ } else {
+ rfbLog("not a control frame\n");
+ /* not a control frame, check for continuation opcode */
+ if (wsctx->header.opcode == WS_OPCODE_CONTINUATION) {
+ rfbLog("cont_frame\n");
+ /* do we have state (i.e., opcode) for continuation frame? */
+ if (wsctx->continuation_opcode == WS_OPCODE_INVALID) {
+ rfbErr("no continuation state\n");
+ errno = EPROTO;
+ goto err_cleanup_state;
+ }
- /* fin = (header->b0 & 0x80) >> 7; */ /* not used atm */
- wsctx->header.payloadLen = wsctx->header.data->b1 & 0x7f;
- rfbLog("first header bytes received; opcode=%d lenbyte=%d\n", wsctx->header.opcode, wsctx->header.payloadLen);
+ /* otherwise, set opcode = continuation_opcode */
+ wsctx->header.opcode = wsctx->continuation_opcode;
+ rfbLog("set opcode to continuation_opcode: %d\n", wsctx->header.opcode);
+ } else {
+ if (wsctx->header.fin == 0) {
+ wsctx->continuation_opcode = wsctx->header.opcode;
+ } else {
+ wsctx->continuation_opcode = WS_OPCODE_INVALID;
+ }
+ rfbLog("set continuation_opcode to %d\n", wsctx->continuation_opcode);
+ }
+ }
+
+ wsctx->header.payloadLen = (uint64_t)(wsctx->header.data->b1 & 0x7f);
+ rfbLog("first header bytes received; opcode=%d lenbyte=%d fin=%d\n", wsctx->header.opcode, wsctx->header.payloadLen, wsctx->header.fin);
/*
* 4.3. Client-to-Server Masking
@@ -139,8 +199,7 @@ hybiReadHeader(ws_ctx_t *wsctx, int *sockRet, int *nPayload)
if (!(wsctx->header.data->b1 & 0x80)) {
rfbErr("%s: got frame without mask; ret=%d\n", __func__, ret);
errno = EPROTO;
- *sockRet = -1;
- return WS_HYBI_STATE_ERR;
+ goto err_cleanup_state;
}
@@ -158,22 +217,27 @@ hybiReadHeader(ws_ctx_t *wsctx, int *sockRet, int *nPayload)
} else {
/* Incomplete frame header, try again */
rfbErr("%s: incomplete frame header; ret=%d\n", __func__, ret);
- errno = EAGAIN;
- *sockRet = -1;
- return WS_HYBI_STATE_HEADER_PENDING;
+ goto ret_header_pending;
}
+ char *h = wsctx->codeBufDecode;
+ int i;
+ rfbLog("Header:\n");
+ for (i=0; i <10; i++) {
+ rfbLog("0x%02X\n", (unsigned char)h[i]);
+ }
+ rfbLog("\n");
+
/* while RFC 6455 mandates that lengths MUST be encoded with the minimum
* number of bytes, it does not specify for the server how to react on
* 'wrongly' encoded frames --- this implementation rejects them*/
if ((wsctx->header.headerLen > WS_HYBI_HEADER_LEN_SHORT
- && wsctx->header.payloadLen < 126)
+ && wsctx->header.payloadLen < (uint64_t)126)
|| (wsctx->header.headerLen > WS_HYBI_HEADER_LEN_EXTENDED
- && wsctx->header.payloadLen < 65536)) {
+ && wsctx->header.payloadLen < (uint64_t)65536)) {
rfbErr("%s: invalid length field; headerLen=%d payloadLen=%llu\n", __func__, wsctx->header.headerLen, wsctx->header.payloadLen);
errno = EPROTO;
- *sockRet = -1;
- return WS_HYBI_STATE_ERR;
+ goto err_cleanup_state;
}
/* absolute length of frame */
@@ -186,9 +250,20 @@ hybiReadHeader(ws_ctx_t *wsctx, int *sockRet, int *nPayload)
wsctx->readPos = (unsigned char *)(wsctx->codeBufDecode + wsctx->header.headerLen);
*nPayload = wsctx->nReadRaw - wsctx->header.headerLen;
- rfbLog("header complete: state=%d flen=%d writeTo=%p nPayload=%d\n", wsctx->hybiDecodeState, wsctx->nToRead, wsctx->writePos, *nPayload);
+ rfbLog("header complete: state=%d flen=%llu writeTo=%p nPayload=%d\n", wsctx->hybiDecodeState, wsctx->nToRead, wsctx->writePos, *nPayload);
return WS_HYBI_STATE_DATA_NEEDED;
+
+ret_header_pending:
+ errno = EAGAIN;
+ *sockRet = -1;
+ return WS_HYBI_STATE_HEADER_PENDING;
+
+err_cleanup_state:
+ *sockRet = -1;
+err_cleanup_state_sock_closed:
+ hybiDecodeCleanupComplete(wsctx);
+ return WS_HYBI_STATE_ERR;
}
static int
@@ -248,6 +323,7 @@ hybiReadAndDecode(ws_ctx_t *wsctx, char *dst, int len, int *sockRet, int nInBuf)
/* -1 accounts for potential '\0' terminator for base64 decoding */
bufsize = wsctx->codeBufDecode + ARRAYSIZE(wsctx->codeBufDecode) - wsctx->writePos - 1;
+ rfbLog("bufsize=%d\n", bufsize);
if (hybiRemaining(wsctx) > bufsize) {
nextRead = bufsize;
} else {
@@ -453,11 +529,18 @@ spor:
/* rfbLog("%s: ret: %d/%d\n", __func__, result, len); */
if (wsctx->hybiDecodeState == WS_HYBI_STATE_FRAME_COMPLETE) {
rfbLog("frame received successfully, cleaning up: read=%d hlen=%d plen=%d\n", wsctx->header.nRead, wsctx->header.headerLen, wsctx->header.payloadLen);
- /* frame finished, cleanup state */
- hybiDecodeCleanup(wsctx);
+ if (wsctx->header.fin && !isControlFrame(wsctx)) {
+ /* frame finished, cleanup state */
+ hybiDecodeCleanupComplete(wsctx);
+ } else {
+ /* always retain continuation opcode for unfinished data frames
+ * or control frames, which may interleave with data frames */
+ hybiDecodeCleanupForContinuation(wsctx);
+ }
} else if (wsctx->hybiDecodeState == WS_HYBI_STATE_ERR) {
- hybiDecodeCleanup(wsctx);
+ hybiDecodeCleanupComplete(wsctx);
}
+
rfbLog("%s_exit: len=%d; "
"CTX: readlen=%d readPos=%p "
"writePos=%p "
diff --git a/libvncserver/ws_decode.h b/libvncserver/ws_decode.h
index 0dcbc83..07d37bd 100644
--- a/libvncserver/ws_decode.h
+++ b/libvncserver/ws_decode.h
@@ -27,16 +27,11 @@
#endif
#define B64LEN(__x) (((__x + 2) / 3) * 12 / 3)
-#define WSHLENMAX 14 /* 2 + sizeof(uint64_t) + sizeof(uint32_t) */
+#define WSHLENMAX 14LL /* 2 + sizeof(uint64_t) + sizeof(uint32_t) */
#define WS_HYBI_MASK_LEN 4
#define ARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))) / (size_t)(!(sizeof(a) % sizeof((a[0])))))
-enum {
- WEBSOCKETS_VERSION_HIXIE,
- WEBSOCKETS_VERSION_HYBI
-};
-
struct ws_ctx_s;
typedef struct ws_ctx_s ws_ctx_t;
@@ -111,9 +106,11 @@ typedef struct ws_header_data_s {
/** length of frame header including payload len, but without mask */
int headerLen;
/** length of the payload data */
- int payloadLen;
+ uint64_t payloadLen;
/** opcode */
unsigned char opcode;
+ /** fin bit */
+ unsigned char fin;
} ws_header_data_t;
typedef struct ws_ctx_s {
@@ -125,11 +122,11 @@ typedef struct ws_ctx_s {
int hybiDecodeState;
char carryBuf[3]; /* For base64 carry-over */
int carrylen;
- int version;
int base64;
ws_header_data_t header;
- int nReadRaw;
- int nToRead;
+ uint64_t nReadRaw;
+ uint64_t nToRead;
+ unsigned char continuation_opcode;
wsEncodeFunc encode;
wsDecodeFunc decode;
ctxInfo_t ctxInfo;
@@ -137,15 +134,16 @@ typedef struct ws_ctx_s {
enum
{
- WS_OPCODE_CONTINUATION = 0x0,
- WS_OPCODE_TEXT_FRAME,
- WS_OPCODE_BINARY_FRAME,
- WS_OPCODE_CLOSE = 0x8,
- WS_OPCODE_PING,
- WS_OPCODE_PONG
+ WS_OPCODE_CONTINUATION = 0x00,
+ WS_OPCODE_TEXT_FRAME = 0x01,
+ WS_OPCODE_BINARY_FRAME = 0x02,
+ WS_OPCODE_CLOSE = 0x08,
+ WS_OPCODE_PING = 0x09,
+ WS_OPCODE_PONG = 0x0A,
+ WS_OPCODE_INVALID = 0xFF
};
int webSocketsDecodeHybi(ws_ctx_t *wsctx, char *dst, int len);
-void hybiDecodeCleanup(ws_ctx_t *wsctx);
+void hybiDecodeCleanupComplete(ws_ctx_t *wsctx);
#endif
diff --git a/test/wsmaketestframe.py b/test/wsmaketestframe.py
index 1d4d24d..fc03e39 100755
--- a/test/wsmaketestframe.py
+++ b/test/wsmaketestframe.py
@@ -42,12 +42,12 @@ def add_field(s, name, value, first=False):
class Testframe():
- def __init__(self, frame, descr, modify_bytes={}, experrno=0, mask=True):
+ def __init__(self, frame, descr, modify_bytes={}, experrno=0, mask=True, opcode_overwrite=False):
self.frame = frame
self.descr = descr
self.modify_bytes = modify_bytes
self.experrno = experrno
- self.b64 = True if frame.opcode == 1 else False
+ self.b64 = True if frame.opcode == 1 or opcode_overwrite == 1 else False
self.mask = mask
def to_carray_initializer(self, buf):
@@ -110,7 +110,14 @@ flist.append(Testframe(websockets.framing.Frame(1, 8, bytearray(list([0x03, 0xEB
### invalid header values
flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("Testit", encoding="utf-8")), "Invalid frame: Wrong masking", experrno="EPROTO", mask=False))
flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("..Lore Ipsum", encoding="utf-8")), "Invalid frame: Length of < 126 with add. 16 bit len field", experrno="EPROTO", modify_bytes={ 1: 0xFE, 2: 0x00, 3: 0x0F}))
-flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("........Lore Ipsum", encoding="utf-8")), "Invalid frame: Length of < 126 with add. 64 bit len field", experrno="EPROTO", modify_bytes={ 1: 0xFF, 2: 0x00, 3: 0x00, 4: 0x00, 5: 0x00, 6: 0x80, 7: 0x40}))
+flist.append(Testframe(websockets.framing.Frame(1, 1, bytearray("........Lore Ipsum", encoding="utf-8")), "Invalid frame: Length of < 126 with add. 64 bit len field", experrno="EPROTO", modify_bytes={ 1: 0xFF, 2: 0x00, 3: 0x00, 4: 0x00, 5: 0x00, 6: 0x00, 7: 0x00, 8: 0x80, 9: 0x40}))
+
+frag1 = websockets.framing.Frame(0, 1, bytearray("This is a fragmented websocket...", encoding="utf-8"))
+frag2 = websockets.framing.Frame(0, 0, bytearray("... and it goes on...", encoding="utf-8"))
+frag3 = websockets.framing.Frame(1, 0, bytearray("and on and stop", encoding="utf-8"))
+flist.append(Testframe(frag1, "Continuation test frag1"))
+flist.append(Testframe(frag2, "Continuation test frag2", opcode_overwrite=1))
+flist.append(Testframe(frag3, "Continuation test frag3", opcode_overwrite=1))
s = "struct ws_frame_test tests[] = {\n"
for i in range(len(flist)):
@@ -120,5 +127,5 @@ for i in range(len(flist)):
s += "\n"
s += "};\n"
-with open("wstestdata.c", "w") as cdatafile:
+with open("wstestdata.inc", "w") as cdatafile:
cdatafile.write(s)
diff --git a/test/wstest.c b/test/wstest.c
index 69cd174..042b75b 100644
--- a/test/wstest.c
+++ b/test/wstest.c
@@ -98,10 +98,10 @@ static int emu_read(void *ctx, char *dst, size_t len)
rfbLog("emu_read called with dst=%p and len=%lu\n", dst, len);
if (ft->simulate_sock_malfunction_at > 0 && ft->simulate_sock_malfunction_at == ft->i) {
rfbLog("simulating IO error with errno=%d\n", ft->errno_val);
- errno = ft->errno_val;
+ errno = ft->errno_val;
return -1;
}
-
+
/* return something */
r = rand();
modu = (ft->frame + ft->frame_len) - ft->pos;
@@ -130,7 +130,7 @@ static uint64_t run_test(struct ws_frame_test *ft, ws_ctx_t *ctx)
while (nleft > 0) {
rfbLog("calling ws_decode with dst=%p, len=%lu\n", dst, nleft);
n = ctx->decode(ctx, dst, nleft);
- rfbLog("read n=%ld\n", n);
+ rfbLog("read n=%ld\n", n);
if (n == 0) {
if (ft->close_sock_at > 0) {
return OK;
@@ -155,7 +155,7 @@ static uint64_t run_test(struct ws_frame_test *ft, ws_ctx_t *ctx)
rfbLog("read n=%ld from decode; dst=%p, nleft=%lu\n", n, dst, nleft);
}
}
-
+
if (memcmp(ft->expectedDecodeBuf, dstbuf, ft->raw_payload_len) != 0) {
ft->expectedDecodeBuf[ft->raw_payload_len] = '\0';
dstbuf[ft->raw_payload_len] = '\0';
@@ -168,24 +168,23 @@ static uint64_t run_test(struct ws_frame_test *ft, ws_ctx_t *ctx)
int main()
-{
+{
ws_ctx_t ctx;
int retall= 0;
int i;
- srand(RND_SEED);
+ srand(RND_SEED);
+ hybiDecodeCleanupComplete(&ctx);
+ ctx.decode = webSocketsDecodeHybi;
+ ctx.ctxInfo.readFunc = emu_read;
+ rfbLog = logtest;
+ rfbErr = logtest;
+
for (i = 0; i < ARRAYSIZE(tests); i++) {
int ret;
+ /* reset output log buffer to begin */
el_pos = el_log;
- rfbLog = logtest;
- rfbErr = logtest;
-
- hybiDecodeCleanup(&ctx);
- ctx.decode = webSocketsDecodeHybi;
- ctx.version = WEBSOCKETS_VERSION_HYBI;
-
- ctx.ctxInfo.readFunc = emu_read;
ret = run_test(&tests[i], &ctx);
printf("%s: \"%s\"\n", ret == 0 ? "PASS" : "FAIL", tests[i].descr);
@@ -198,7 +197,7 @@ int main()
return retall;
}
-#else
+#else
int main() {
return 0;
diff --git a/test/wstestdata.inc b/test/wstestdata.inc
index 9dc919e..595b891 100644
--- a/test/wstestdata.inc
+++ b/test/wstestdata.inc
@@ -1,6 +1,6 @@
struct ws_frame_test tests[] = {
{
- .frame={0X81,0X88,0XB7,0XDB,0X16,0X16,0XE1,0X9C,0X40,0X6C,0XD3,0X9C,0X7A,0X26},
+ .frame={0X81,0X88,0X2F,0X2A,0X17,0X41,0X79,0X6D,0X41,0X3B,0X4B,0X6D,0X7B,0X71},
.expectedDecodeBuf={0X54,0X65,0X73,0X74,0X69,0X74},
.frame_len=14,
.raw_payload_len=6,
@@ -12,7 +12,7 @@ struct ws_frame_test tests[] = {
.close_sock_at=0
},
{
- .frame={0X81,0XFE,0X00,0XD4,0X67,0XFE,0X8A,0X31,0X35,0X90,0XC0,0X59,0X05,0XA9,0XDF,0X48,0X2E,0XB9,0XD8,0X47,0X3D,0XA6,0XC7,0X56,0X3E,0XCC,0XB3,0X44,0X03,0XB9,0XCC,0X41,0X05,0X97,0XC8,0X45,0X03,0XA9,0XC4,0X5E,0X2E,0XB9,0XBB,0X47,0X04,0X93,0XDF,0X56,0X03,0XB9,0XDC,0X05,0X03,0XBD,0XC8,0X59,0X05,0X93,0XDB,0X56,0X3D,0XA6,0XD0,0X5D,0X05,0X97,0XC8,0X5F,0X05,0XCC,0XDC,0X4B,0X2E,0XB9,0XC0,0X5D,0X02,0XA9,0XB3,0X44,0X3D,0XBD,0XC8,0X01,0X06,0XB9,0XDF,0X56,0X2A,0XAA,0XC3,0X03,0X2E,0XB9,0XC0,0X04,0X03,0XB9,0XDF,0X56,0X05,0XB9,0XDC,0X44,0X2E,0XB9,0XD0,0X41,0X3D,0XA9,0XF2,0X5A,0X2B,0X97,0XC8,0X76,0X04,0X93,0XCC,0X45,0X3D,0XAA,0XC3,0X56,0X3D,0XB9,0XB3,0X5D,0X04,0X87,0XC8,0X5B,0X05,0XCC,0XBF,0X01,0X3E,0XA9,0XE6,0X44,0X2E,0XB9,0XBB,0X00,0X3E,0XCC,0XED,0X56,0X05,0XA9,0XB3,0X48,0X3D,0XAD,0XC8,0X01,0X3D,0XA6,0XE2,0X01,0X2E,0XB9,0XCC,0X44,0X3D,0XBD,0XC8,0X5D,0X03,0X93,0XDC,0X44,0X2E,0XB9,0XEE,0X47,0X3D,0XA6,0XC7,0X56,0X3E,0X93,0XDC,0X04,0X05,0XCC,0XBF,0X5A,0X2E,0XB6,0XD8,0X5E,0X3D,0XAD,0XCB,0X49,0X2A,0X94,0XD3,0X56,0X3E,0X90,0XE6,0X01,0X3D,0XAD,0XC8,0X42,0X3D,0XA9,0XBE,0X56,0X3D,0X93,0XE6,0X5D,0X05,0XB9,0XDB,0X44},
+ .frame={0X81,0XFE,0X00,0XD4,0X66,0X27,0XE5,0X24,0X34,0X49,0XAF,0X4C,0X04,0X70,0XB0,0X5D,0X2F,0X60,0XB7,0X52,0X3C,0X7F,0XA8,0X43,0X3F,0X15,0XDC,0X51,0X02,0X60,0XA3,0X54,0X04,0X4E,0XA7,0X50,0X02,0X70,0XAB,0X4B,0X2F,0X60,0XD4,0X52,0X05,0X4A,0XB0,0X43,0X02,0X60,0XB3,0X10,0X02,0X64,0XA7,0X4C,0X04,0X4A,0XB4,0X43,0X3C,0X7F,0XBF,0X48,0X04,0X4E,0XA7,0X4A,0X04,0X15,0XB3,0X5E,0X2F,0X60,0XAF,0X48,0X03,0X70,0XDC,0X51,0X3C,0X64,0XA7,0X14,0X07,0X60,0XB0,0X43,0X2B,0X73,0XAC,0X16,0X2F,0X60,0XAF,0X11,0X02,0X60,0XB0,0X43,0X04,0X60,0XB3,0X51,0X2F,0X60,0XBF,0X54,0X3C,0X70,0X9D,0X4F,0X2A,0X4E,0XA7,0X63,0X05,0X4A,0XA3,0X50,0X3C,0X73,0XAC,0X43,0X3C,0X60,0XDC,0X48,0X05,0X5E,0XA7,0X4E,0X04,0X15,0XD0,0X14,0X3F,0X70,0X89,0X51,0X2F,0X60,0XD4,0X15,0X3F,0X15,0X82,0X43,0X04,0X70,0XDC,0X5D,0X3C,0X74,0XA7,0X14,0X3C,0X7F,0X8D,0X14,0X2F,0X60,0XA3,0X51,0X3C,0X64,0XA7,0X48,0X02,0X4A,0XB3,0X51,0X2F,0X60,0X81,0X52,0X3C,0X7F,0XA8,0X43,0X3F,0X4A,0XB3,0X11,0X04,0X15,0XD0,0X4F,0X2F,0X6F,0XB7,0X4B,0X3C,0X74,0XA4,0X5C,0X2B,0X4D,0XBC,0X43,0X3F,0X49,0X89,0X14,0X3C,0X74,0XA7,0X57,0X3C,0X70,0XD1,0X43,0X3C,0X4A,0X89,0X48,0X04,0X60,0XB4,0X51},
.expectedDecodeBuf={0X46,0X72,0X61,0X6D,0X65,0X32,0X20,0X64,0X6F,0X65,0X73,0X20,0X63,0X6F,0X6E,0X74,0X61,0X69,0X6E,0X20,0X6D,0X75,0X63,0X68,0X20,0X6D,0X6F,0X72,0X65,0X20,0X74,0X65,0X78,0X74,0X20,0X61,0X6E,0X64,0X20,0X65,0X76,0X65,0X6E,0X20,0X67,0X6F,0X65,0X73,0X20,0X62,0X65,0X79,0X6F,0X6E,0X64,0X20,0X74,0X68,0X65,0X20,0X31,0X32,0X36,0X20,0X62,0X79,0X74,0X65,0X20,0X6C,0X65,0X6E,0X20,0X66,0X69,0X65,0X6C,0X64,0X2E,0X20,0X46,0X72,0X61,0X6D,0X65,0X32,0X20,0X64,0X6F,0X65,0X73,0X20,0X63,0X6F,0X6E,0X74,0X61,0X69,0X6E,0X20,0X6D,0X75,0X63,0X68,0X20,0X6D,0X6F,0X72,0X65,0X20,0X74,0X65,0X78,0X74,0X20,0X61,0X6E,0X64,0X20,0X65,0X76,0X65,0X6E,0X20,0X67,0X6F,0X65,0X73,0X20,0X62,0X65,0X79,0X6F,0X6E,0X64,0X20,0X74,0X68,0X65,0X20,0X31,0X32,0X36,0X20,0X62,0X79,0X74,0X65,0X20,0X6C,0X65,0X6E,0X20,0X66,0X69,0X65,0X6C,0X64,0X2E},
.frame_len=220,
.raw_payload_len=159,
@@ -24,7 +24,7 @@ struct ws_frame_test tests[] = {
.close_sock_at=0
},
{
- .frame={0X82,0X86,0X90,0X5E,0X2B,0X8E,0XC4,0X3B,0X58,0XFA,0XF9,0X2A},
+ .frame={0X82,0X86,0XDD,0X9B,0XD8,0X56,0X89,0XFE,0XAB,0X22,0XB4,0XEF},
.expectedDecodeBuf={0X54,0X65,0X73,0X74,0X69,0X74},
.frame_len=12,
.raw_payload_len=6,
@@ -36,7 +36,7 @@ struct ws_frame_test tests[] = {
.close_sock_at=0
},
{
- .frame={0X82,0XFE,0X00,0X9F,0X7D,0X97,0X6B,0XA2,0X3B,0XE5,0X0A,0XCF,0X18,0XA5,0X4B,0XC6,0X12,0XF2,0X18,0X82,0X1E,0XF8,0X05,0XD6,0X1C,0XFE,0X05,0X82,0X10,0XE2,0X08,0XCA,0X5D,0XFA,0X04,0XD0,0X18,0XB7,0X1F,0XC7,0X05,0XE3,0X4B,0XC3,0X13,0XF3,0X4B,0XC7,0X0B,0XF2,0X05,0X82,0X1A,0XF8,0X0E,0XD1,0X5D,0XF5,0X0E,0XDB,0X12,0XF9,0X0F,0X82,0X09,0XFF,0X0E,0X82,0X4C,0XA5,0X5D,0X82,0X1F,0XEE,0X1F,0XC7,0X5D,0XFB,0X0E,0XCC,0X5D,0XF1,0X02,0XC7,0X11,0XF3,0X45,0X82,0X3B,0XE5,0X0A,0XCF,0X18,0XA5,0X4B,0XC6,0X12,0XF2,0X18,0X82,0X1E,0XF8,0X05,0XD6,0X1C,0XFE,0X05,0X82,0X10,0XE2,0X08,0XCA,0X5D,0XFA,0X04,0XD0,0X18,0XB7,0X1F,0XC7,0X05,0XE3,0X4B,0XC3,0X13,0XF3,0X4B,0XC7,0X0B,0XF2,0X05,0X82,0X1A,0XF8,0X0E,0XD1,0X5D,0XF5,0X0E,0XDB,0X12,0XF9,0X0F,0X82,0X09,0XFF,0X0E,0X82,0X4C,0XA5,0X5D,0X82,0X1F,0XEE,0X1F,0XC7,0X5D,0XFB,0X0E,0XCC,0X5D,0XF1,0X02,0XC7,0X11,0XF3,0X45},
+ .frame={0X82,0XFE,0X00,0X9F,0XB5,0X6E,0X7F,0X4C,0XF3,0X1C,0X1E,0X21,0XD0,0X5C,0X5F,0X28,0XDA,0X0B,0X0C,0X6C,0XD6,0X01,0X11,0X38,0XD4,0X07,0X11,0X6C,0XD8,0X1B,0X1C,0X24,0X95,0X03,0X10,0X3E,0XD0,0X4E,0X0B,0X29,0XCD,0X1A,0X5F,0X2D,0XDB,0X0A,0X5F,0X29,0XC3,0X0B,0X11,0X6C,0XD2,0X01,0X1A,0X3F,0X95,0X0C,0X1A,0X35,0XDA,0X00,0X1B,0X6C,0XC1,0X06,0X1A,0X6C,0X84,0X5C,0X49,0X6C,0XD7,0X17,0X0B,0X29,0X95,0X02,0X1A,0X22,0X95,0X08,0X16,0X29,0XD9,0X0A,0X51,0X6C,0XF3,0X1C,0X1E,0X21,0XD0,0X5C,0X5F,0X28,0XDA,0X0B,0X0C,0X6C,0XD6,0X01,0X11,0X38,0XD4,0X07,0X11,0X6C,0XD8,0X1B,0X1C,0X24,0X95,0X03,0X10,0X3E,0XD0,0X4E,0X0B,0X29,0XCD,0X1A,0X5F,0X2D,0XDB,0X0A,0X5F,0X29,0XC3,0X0B,0X11,0X6C,0XD2,0X01,0X1A,0X3F,0X95,0X0C,0X1A,0X35,0XDA,0X00,0X1B,0X6C,0XC1,0X06,0X1A,0X6C,0X84,0X5C,0X49,0X6C,0XD7,0X17,0X0B,0X29,0X95,0X02,0X1A,0X22,0X95,0X08,0X16,0X29,0XD9,0X0A,0X51},
.expectedDecodeBuf={0X46,0X72,0X61,0X6D,0X65,0X32,0X20,0X64,0X6F,0X65,0X73,0X20,0X63,0X6F,0X6E,0X74,0X61,0X69,0X6E,0X20,0X6D,0X75,0X63,0X68,0X20,0X6D,0X6F,0X72,0X65,0X20,0X74,0X65,0X78,0X74,0X20,0X61,0X6E,0X64,0X20,0X65,0X76,0X65,0X6E,0X20,0X67,0X6F,0X65,0X73,0X20,0X62,0X65,0X79,0X6F,0X6E,0X64,0X20,0X74,0X68,0X65,0X20,0X31,0X32,0X36,0X20,0X62,0X79,0X74,0X65,0X20,0X6C,0X65,0X6E,0X20,0X66,0X69,0X65,0X6C,0X64,0X2E,0X20,0X46,0X72,0X61,0X6D,0X65,0X32,0X20,0X64,0X6F,0X65,0X73,0X20,0X63,0X6F,0X6E,0X74,0X61,0X69,0X6E,0X20,0X6D,0X75,0X63,0X68,0X20,0X6D,0X6F,0X72,0X65,0X20,0X74,0X65,0X78,0X74,0X20,0X61,0X6E,0X64,0X20,0X65,0X76,0X65,0X6E,0X20,0X67,0X6F,0X65,0X73,0X20,0X62,0X65,0X79,0X6F,0X6E,0X64,0X20,0X74,0X68,0X65,0X20,0X31,0X32,0X36,0X20,0X62,0X79,0X74,0X65,0X20,0X6C,0X65,0X6E,0X20,0X66,0X69,0X65,0X6C,0X64,0X2E},
.frame_len=167,
.raw_payload_len=159,
@@ -48,7 +48,7 @@ struct ws_frame_test tests[] = {
.close_sock_at=0
},
{
- .frame={0X88,0X82,0X71,0X1D,0X00,0XFE,0X72,0XF6},
+ .frame={0X88,0X82,0X6B,0X33,0X77,0X94,0X68,0XD8},
.expectedDecodeBuf={0X03,0XEB},
.frame_len=8,
.raw_payload_len=2,
@@ -60,7 +60,7 @@ struct ws_frame_test tests[] = {
.close_sock_at=0
},
{
- .frame={0X88,0XAD,0XD0,0X8D,0X26,0XD8,0XD3,0X66,0X6F,0XFF,0XBD,0XAD,0X47,0XF8,0XB3,0XE1,0X49,0XAB,0XB5,0XAD,0X54,0XBD,0XB1,0XFE,0X49,0XB6,0XF0,0XEC,0X48,0XBC,0XF0,0XE0,0X53,0XBB,0XB8,0XAD,0X4B,0XB7,0XA2,0XE8,0X06,0XAC,0XB8,0XEC,0X48,0XF8,0XA4,0XE5,0X47,0XAC,0XF1},
+ .frame={0X88,0XAD,0X4B,0XA1,0XCE,0XE8,0X48,0X4A,0X87,0XCF,0X26,0X81,0XAF,0XC8,0X28,0XCD,0XA1,0X9B,0X2E,0X81,0XBC,0X8D,0X2A,0XD2,0XA1,0X86,0X6B,0XC0,0XA0,0X8C,0X6B,0XCC,0XBB,0X8B,0X23,0X81,0XA3,0X87,0X39,0XC4,0XEE,0X9C,0X23,0XC0,0XA0,0XC8,0X3F,0XC9,0XAF,0X9C,0X6A},
.expectedDecodeBuf={0X03,0XEB,0X49,0X27,0X6D,0X20,0X61,0X20,0X63,0X6C,0X6F,0X73,0X65,0X20,0X72,0X65,0X61,0X73,0X6F,0X6E,0X20,0X61,0X6E,0X64,0X20,0X6D,0X75,0X63,0X68,0X20,0X6D,0X6F,0X72,0X65,0X20,0X74,0X68,0X61,0X6E,0X20,0X74,0X68,0X61,0X74,0X21},
.frame_len=51,
.raw_payload_len=45,
@@ -84,7 +84,7 @@ struct ws_frame_test tests[] = {
.close_sock_at=0
},
{
- .frame={0X81,0XFE,0X00,0X0F,0X24,0X22,0X8D,0X9C,0X11,0X6F,0XA3,0XC6,0X6E,0X4E,0X88,0XB0,0X48,0X55,0XA2,0XC6,0X72,0X56},
+ .frame={0X81,0XFE,0X00,0X0F,0X71,0XE9,0X29,0X79,0X44,0XA4,0X07,0X23,0X3B,0X85,0X2C,0X55,0X1D,0X9E,0X06,0X23,0X27,0X9D},
.expectedDecodeBuf={0X2E,0XFE,0X00,0X0F,0X72,0X65,0X20,0X49,0X70,0X73,0X75,0X6D},
.frame_len=22,
.raw_payload_len=12,
@@ -96,8 +96,8 @@ struct ws_frame_test tests[] = {
.close_sock_at=0
},
{
- .frame={0X81,0XFF,0X00,0X00,0X00,0X00,0X80,0X40,0X7D,0XBB,0X03,0X56,0X7D,0XBB,0X03,0X56,0X7C,0X83,0X2D,0X0C,0X03,0XA2,0X06,0X7A,0X25,0XB9,0X2C,0X0C,0X1F,0XBA},
- .expectedDecodeBuf={0X2E,0XFF,0X00,0X00,0X00,0X00,0X80,0X40,0X4C,0X6F,0X72,0X65,0X20,0X49,0X70,0X73,0X75,0X6D},
+ .frame={0X81,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0X80,0X40,0X2F,0X40,0XF3,0X5B,0X2F,0X40,0XF2,0X63,0X01,0X1A,0X8D,0X42,0X2A,0X6C,0XAB,0X59,0X00,0X1A,0X91,0X5A},
+ .expectedDecodeBuf={0X2E,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0X80,0X40,0X72,0X65,0X20,0X49,0X70,0X73,0X75,0X6D},
.frame_len=30,
.raw_payload_len=18,
.expected_errno=EPROTO,
@@ -106,5 +106,41 @@ struct ws_frame_test tests[] = {
.simulate_sock_malfunction_at=0,
.errno_val=0,
.close_sock_at=0
+ },
+ {
+ .frame={0X01,0XAC,0XC9,0X6E,0XC7,0X6E,0X9F,0X29,0XAF,0X1E,0XAA,0X17,0X85,0X1E,0XAA,0X17,0X85,0X06,0X80,0X29,0X9D,0X17,0X90,0X39,0XA3,0X1A,0X93,0X39,0XF2,0X5E,0X93,0X39,0X96,0X09,0XAD,0X5C,0X91,0X07,0XAA,0X5C,0XFE,0X04,0XA8,0X5C,0X91,0X5E,0X85,0X07,0XF3,0X1B},
+ .expectedDecodeBuf={0X54,0X68,0X69,0X73,0X20,0X69,0X73,0X20,0X61,0X20,0X66,0X72,0X61,0X67,0X6D,0X65,0X6E,0X74,0X65,0X64,0X20,0X77,0X65,0X62,0X73,0X6F,0X63,0X6B,0X65,0X74,0X2E,0X2E,0X2E},
+ .frame_len=50,
+ .raw_payload_len=33,
+ .expected_errno=0,
+ .descr="Continuation test frag1",
+ .i=0,
+ .simulate_sock_malfunction_at=0,
+ .errno_val=0,
+ .close_sock_at=0
+ },
+ {
+ .frame={0X00,0X9C,0X52,0XBC,0XD5,0X99,0X1E,0XD5,0XE1,0XEC,0X1B,0XFB,0X93,0XEC,0X08,0XFF,0X97,0XE9,0X36,0XFF,0X97,0XF7,0X30,0X8E,0X83,0XE3,0X1B,0XFB,0XEC,0XEC,0X1E,0XD5,0XE1,0XEC},
+ .expectedDecodeBuf={0X2E,0X2E,0X2E,0X20,0X61,0X6E,0X64,0X20,0X69,0X74,0X20,0X67,0X6F,0X65,0X73,0X20,0X6F,0X6E,0X2E,0X2E,0X2E},
+ .frame_len=34,
+ .raw_payload_len=21,
+ .expected_errno=0,
+ .descr="Continuation test frag2",
+ .i=0,
+ .simulate_sock_malfunction_at=0,
+ .errno_val=0,
+ .close_sock_at=0
+ },
+ {
+ .frame={0X80,0X94,0X3B,0X88,0XA1,0XE9,0X62,0XDF,0X94,0X82,0X72,0XCF,0X98,0X9C,0X72,0XCF,0XE7,0X9C,0X61,0XCB,0XE3,0X93,0X5F,0XCF,0X98,0X9E},
+ .expectedDecodeBuf={0X61,0X6E,0X64,0X20,0X6F,0X6E,0X20,0X61,0X6E,0X64,0X20,0X73,0X74,0X6F,0X70},
+ .frame_len=26,
+ .raw_payload_len=15,
+ .expected_errno=0,
+ .descr="Continuation test frag3",
+ .i=0,
+ .simulate_sock_malfunction_at=0,
+ .errno_val=0,
+ .close_sock_at=0
}
};