ws: tests and fixes

This started out as regression tests for the `curl_ws_recv()` and
`curl_ws_send()` implementation and ended up with a bugfix, additional
protocol validation and minor logging improvements.

- Fix reset of fragmented message decoder state when a PING/PONG is
  received in between message fragments.

- Fix undefined behavior (applying zero offset to null pointer) in
  curl_ws_send() when the given buffer is NULL.

- Detect invalid overlong PING/PONG/CLOSE frames.
- Detect invalid fragmented PING/PONG/CLOSE frames.
- Detect invalid sequences of fragmented frames.

  - a) A continuation frame (0x80...) is received without any ongoing
    fragmented message.
  - b) A new fragmented message is started (0x81/0x01/0x82/0x02...)
    before the ongoing fragmented message has terminated.

- Made logs for invalid opcodes easier to understand.
- Moved noisy logs to the `CURL_TRC_WS` log level.
- Unified the prefixes for WebSocket log messages: `[WS] ...`

- Add env var `CURL_WS_FORCE_ZERO_MASK` in debug builds.

  - If set, it forces the bit mask applied to outgoing payloads to
    0x00000000, which effectively means the payload is not masked at
    all. This drastically simplifies defining the expected `<protocol>`
    data in test cases.

- 2700: Frame types
- 2701: Invalid opcode 0x3
- 2702: Invalid opcode 0xB
- 2703: Invalid reserved bit RSV1 _(replaces 2310)_
- 2704: Invalid reserved bit RSV2
- 2705: Invalid reserved bit RSV3
- 2706: Invalid masked server message
- 2707: Peculiar frame sizes _(part. replaces 2311)_
- 2708: Automatic PONG
- 2709: No automatic PONG _(replaces 2312)_
- 2710: Unsolicited PONG
- 2711: Empty PING/PONG/CLOSE
- 2712: Max sized PING/PONG/CLOSE
- 2713: Invalid oversized PING _(replaces 2307)_
- 2714: Invalid oversized PONG
- 2715: Invalid oversized CLOSE
- 2716: Invalid fragmented PING
- 2717: Invalid fragmented PONG
- 2718: Invalid fragmented CLOSE
- 2719: Fragmented messages _(part. replaces 2311)_
- 2720: Fragmented messages with empty fragments
- 2721: Fragmented messages with interleaved pong
- 2722: Invalid fragmented message without initial frame
- 2723: Invalid fragmented message without final frame

- 2305: curl_ws_recv() loop reading three larger frames
  - This test involuntarily sent an invalid sequence of opcodes (0x01...,0x01...,0x81...) , but neither libcurl nor the test caught this! The correct sequence was tested in 2311 (0x01...,0x00...,0x80...). See below for 2311.
  - Validation of the opcode sequence was added to libcurl and is now tested in 2723.
  - Superseded by 2719 (fragmented message) and 2707 (large frames).
- 2307: overlong PING payload
  - The tested PING payload length check was actually missing, but the test didn't catch this since it involuntarily sent an invalid opcode (0x19... instead of 0x89...) so that the expected error occurred, but for the wrong reason.
  - Superseded by 2713.
- 2310: unknown reserved bit set in frame header
  - Superseded by 2703 and extended by 2704 and 2705.
- 2311: curl_ws_recv() read fragmented message
  - Superseded by 2719 (fragmented message) and 2707 (large frames).
- 2312: WebSockets no auto ping
  - Superseded by 2709.

- No tests for `CURLOPT_WRITEFUNCTION`.
- No tests for sending of invalid frames/fragments.

Closes #17136
This commit is contained in:
Ruocco, Calvin 2025-04-14 17:59:45 +02:00 committed by Daniel Stenberg
parent 04c3895ceb
commit d3594be653
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
41 changed files with 2224 additions and 828 deletions

View file

@ -258,8 +258,8 @@ test2100 test2101 test2102 \
\
test2200 test2201 test2202 test2203 test2204 test2205 \
\
test2300 test2301 test2302 test2303 test2304 test2305 test2306 test2307 \
test2308 test2309 test2310 test2311 test2312 \
test2300 test2301 test2302 test2303 test2304 test2306 \
test2308 test2309 \
\
test2400 test2401 test2402 test2403 test2404 test2405 test2406 \
\
@ -267,6 +267,10 @@ test2500 test2501 test2502 test2503 \
\
test2600 test2601 test2602 test2603 test2604 \
\
test2700 test2701 test2702 test2703 test2704 test2705 test2706 test2707 \
test2708 test2709 test2710 test2711 test2712 test2713 test2714 test2715 \
test2716 test2717 test2718 test2719 test2720 test2721 test2722 test2723 \
\
test3000 test3001 test3002 test3003 test3004 test3005 test3006 test3007 \
test3008 test3009 test3010 test3011 test3012 test3013 test3014 test3015 \
test3016 test3017 test3018 test3019 test3020 test3021 test3022 test3023 \

View file

@ -6,17 +6,16 @@ WebSockets
</info>
#
# Sends a PING + a 5 byte hello TEXT
# Close connection during websocket upgrade
<reply>
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets swsclose
Server: test-server/fake
Upgrade: websocket
Connection: Upgrade
Something: else
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%89%00%81%05hello]hex%
HTTP/1.1 101 Switching to WebSockets swsclose
Server: test-server/fake
Upgrade: websocket
Connection: Upgrade
Something: else
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
</data>
# allow upgrade
<servercmd>
@ -53,7 +52,7 @@ ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
<protocol nocheck="yes" crlf="yes">
GET /%TESTNUMBER HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: websocket/2304
User-Agent: websocket/%TESTNUMBER
Accept: */*
Upgrade: websocket
Connection: Upgrade

View file

@ -1,59 +0,0 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
#
# Sends three 4097 bytes TEXT frames, as one single message
<reply>
<data nocheck="yes">
HTTP/1.1 101 Switching to WebSockets
Server: test-server/fake
Upgrade: websocket
Connection: Upgrade
Something: else
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%01%7e%10%01]hex%%repeat[256 x helothisisdaniel]%
%hex[%01%7e%10%01]hex%%repeat[256 x helothisisdaniel]%
%hex[%81%7e%10%01]hex%%repeat[256 x helothisisdaniel]%
</data>
# allow upgrade
<servercmd>
upgrade
</servercmd>
</reply>
#
# Client-side
<client>
# require debug for the forced CURL_ENTROPY
<features>
Debug
ws
</features>
<server>
http
</server>
<name>
WebSocket curl_ws_recv() loop reading three larger frames
</name>
<tool>
lib%TESTNUMBER
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER %LOGDIR/save%TESTNUMBER
</command>
</client>
#
<verify>
<file name="%LOGDIR/save%TESTNUMBER" mode="text">
%repeat[256 x helothisisdaniel]%
%repeat[256 x helothisisdaniel]%
%repeat[256 x helothisisdaniel]%
</file>
</verify>
</testcase>

View file

@ -1,70 +0,0 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
#
# Sends a PING with overlong payload
<reply>
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets
Server: test-server/fake
Upgrade: websocket
Connection: Upgrade
Something: else
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%19%7f%ff%30%30%30%30%30%30%30%30%30%30%30%30]hex%
</data>
# allow upgrade
<servercmd>
upgrade
</servercmd>
</reply>
#
# Client-side
<client>
# require debug for the forced CURL_ENTROPY
<features>
Debug
ws
</features>
<server>
http
</server>
<name>
WebSockets, overlong PING payload
</name>
<tool>
lib2302
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
</client>
#
# PONG with no data and the 32 bit mask
#
<verify>
<protocol nocheck="yes" nonewline="yes">
GET /%TESTNUMBER HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: webbie-sox/3
Accept: */*
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: NDMyMTUzMjE2MzIxNzMyMQ==
</protocol>
# 56 == CURLE_RECV_ERROR
<errorcode>
56
</errorcode>
</verify>
</testcase>

View file

@ -1,68 +0,0 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
#
# Sends a PING + a TEXT with RSV1 set
<reply>
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets
Server: test-server/fake
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%89%00%C1%05hello]hex%
</data>
# allow upgrade
<servercmd>
upgrade
</servercmd>
</reply>
#
# Client-side
<client>
# require debug for the forced CURL_ENTROPY
<features>
Debug
ws
</features>
<server>
http
</server>
<name>
WebSockets unknown reserved bit set in frame header
</name>
<tool>
lib%TESTNUMBER
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
</client>
#
# PONG with no data and the 32 bit mask
#
<verify>
<protocol nocheck="yes" nonewline="yes">
GET /%TESTNUMBER HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: webbie-sox/3
Accept: */*
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: NDMyMTUzMjE2MzIxNzMyMQ==
%hex[%8a%808321]hex%
</protocol>
<stdout mode="text">
Returned 56, should be 56.
</stdout>
</verify>
</testcase>

View file

@ -1,59 +0,0 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
#
# Sends three 4097 bytes TEXT frames, as fragments of one 12291 bytes message
<reply>
<data nocheck="yes">
HTTP/1.1 101 Switching to WebSockets
Server: test-server/fake
Upgrade: websocket
Connection: Upgrade
Something: else
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%01%7e%10%01]hex%%repeat[256 x helothisisdaniel]%
%hex[%00%7e%10%01]hex%%repeat[256 x helothisisdaniel]%
%hex[%80%7e%10%01]hex%%repeat[256 x helothisisdaniel]%
</data>
# allow upgrade
<servercmd>
upgrade
</servercmd>
</reply>
#
# Client-side
<client>
# require debug for the forced CURL_ENTROPY
<features>
Debug
ws
</features>
<server>
http
</server>
<name>
WebSocket curl_ws_recv() read fragmented message
</name>
<tool>
lib%TESTNUMBER
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER %LOGDIR/save%TESTNUMBER
</command>
</client>
#
<verify>
<file name="%LOGDIR/save%TESTNUMBER" mode="text">
%repeat[256 x helothisisdaniel]%
%repeat[256 x helothisisdaniel]%
%repeat[256 x helothisisdaniel]%
</file>
</verify>
</testcase>

View file

@ -1,66 +0,0 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
#
# Server-side
<reply>
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets swsclose
Server: test-server/fake
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%89%00]hex%
</data>
# allow upgrade
<servercmd>
upgrade
</servercmd>
</reply>
#
# Client-side
<client>
# for the forced CURL_ENTROPY
<features>
debug
ws
</features>
<server>
http
</server>
<name>
WebSockets no auto ping
</name>
<tool>
lib%TESTNUMBER
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
</client>
#
# Verify data after the test has been "shot"
<verify>
<protocol nocheck="yes">
GET /%TESTNUMBER HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: webbie-sox/3
Accept: */*
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: NDMyMTUzMjE2MzIxNzMyMQ==
</protocol>
<errorcode>
0
</errorcode>
</verify>
</testcase>

76
tests/data/test2700 Normal file
View file

@ -0,0 +1,76 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
<client>
<name>
ws: Frame types
</name>
<features>
Debug
ws
</features>
<server>
http
</server>
<tool>
lib2700
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
<setenv>
CURL_WS_FORCE_ZERO_MASK=1
</setenv>
</client>
<reply>
<servercmd>
upgrade
</servercmd>
# Full list of frames: see <verify.stdout> below
# A TEXT/BINARY/PING/PONG/CLOSE message with payload
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets
Server: server/%TESTNUMBER
Upgrade: Websocket
Connection: Upgrade
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%81%03txt]hex%%hex[%82%03bin]hex%%hex[%89%04ping]hex%%hex[%8a%04pong]hex%%hex[%88%07%03%e8close]hex%
</data>
</reply>
<verify>
# Exact echo of reply data with additional masking
<protocol nonewline="yes">
%hex[%81%83%00%00%00%00txt]hex%%hex[%82%83%00%00%00%00bin]hex%%hex[%89%84%00%00%00%00ping]hex%%hex[%8a%84%00%00%00%00pong]hex%%hex[%88%87%00%00%00%00%03%e8close]hex%
</protocol>
# PING is handled by lib and never given to application
<stdout>
txt fin [3] txt
bin fin [3] bin
ping [4] ping
pong [4] pong
close [7] %hex[%03%e8]hex%close
</stdout>
# CURLE_OK
<errorcode>
0
</errorcode>
# Strip HTTP header from <protocol>
<strip>
^GET /.*
^(Host|User-Agent|Accept|Upgrade|Connection|Sec-WebSocket-(Version|Key)): .*
^\s*$
</strip>
</verify>
</testcase>

72
tests/data/test2701 Normal file
View file

@ -0,0 +1,72 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
<client>
<name>
ws: Invalid opcode 0x3
</name>
<features>
Debug
ws
</features>
<server>
http
</server>
<tool>
lib2700
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
<setenv>
CURL_WS_FORCE_ZERO_MASK=1
</setenv>
</client>
<reply>
<servercmd>
upgrade
</servercmd>
# Full list of frames: see <verify.stdout> below
# An empty frame with the reserved opcode 0x3
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets
Server: server/%TESTNUMBER
Upgrade: Websocket
Connection: Upgrade
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%83%00]hex%
</data>
</reply>
<verify>
# No frames
<protocol nonewline="yes">
</protocol>
# No frames
<stdout nonewline="yes">
</stdout>
# CURLE_RECV_ERROR
<errorcode>
56
</errorcode>
# Strip HTTP header from <protocol>
<strip>
^GET /.*
^(Host|User-Agent|Accept|Upgrade|Connection|Sec-WebSocket-(Version|Key)): .*
^\s*$
</strip>
</verify>
</testcase>

72
tests/data/test2702 Normal file
View file

@ -0,0 +1,72 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
<client>
<name>
ws: Invalid opcode 0xB
</name>
<features>
Debug
ws
</features>
<server>
http
</server>
<tool>
lib2700
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
<setenv>
CURL_WS_FORCE_ZERO_MASK=1
</setenv>
</client>
<reply>
<servercmd>
upgrade
</servercmd>
# Full list of frames: see <verify.stdout> below
# An empty frame with the reserved opcode 0xB
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets
Server: server/%TESTNUMBER
Upgrade: Websocket
Connection: Upgrade
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%8b%00]hex%
</data>
</reply>
<verify>
# No frames
<protocol nonewline="yes">
</protocol>
# No frames
<stdout nonewline="yes">
</stdout>
# CURLE_RECV_ERROR
<errorcode>
56
</errorcode>
# Strip HTTP header from <protocol>
<strip>
^GET /.*
^(Host|User-Agent|Accept|Upgrade|Connection|Sec-WebSocket-(Version|Key)): .*
^\s*$
</strip>
</verify>
</testcase>

72
tests/data/test2703 Normal file
View file

@ -0,0 +1,72 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
<client>
<name>
ws: Invalid reserved bit RSV1
</name>
<features>
Debug
ws
</features>
<server>
http
</server>
<tool>
lib2700
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
<setenv>
CURL_WS_FORCE_ZERO_MASK=1
</setenv>
</client>
<reply>
<servercmd>
upgrade
</servercmd>
# Full list of frames: see <verify.stdout> below
# An empty frame with the RSV1 bit set
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets
Server: server/%TESTNUMBER
Upgrade: Websocket
Connection: Upgrade
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%C1%00]hex%
</data>
</reply>
<verify>
# No frames
<protocol nonewline="yes">
</protocol>
# No frames
<stdout nonewline="yes">
</stdout>
# CURLE_RECV_ERROR
<errorcode>
56
</errorcode>
# Strip HTTP header from <protocol>
<strip>
^GET /.*
^(Host|User-Agent|Accept|Upgrade|Connection|Sec-WebSocket-(Version|Key)): .*
^\s*$
</strip>
</verify>
</testcase>

72
tests/data/test2704 Normal file
View file

@ -0,0 +1,72 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
<client>
<name>
ws: Invalid reserved bit RSV2
</name>
<features>
Debug
ws
</features>
<server>
http
</server>
<tool>
lib2700
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
<setenv>
CURL_WS_FORCE_ZERO_MASK=1
</setenv>
</client>
<reply>
<servercmd>
upgrade
</servercmd>
# Full list of frames: see <verify.stdout> below
# An empty frame with the RSV2 bit set
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets
Server: server/%TESTNUMBER
Upgrade: Websocket
Connection: Upgrade
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%A1%00]hex%
</data>
</reply>
<verify>
# No frames
<protocol nonewline="yes">
</protocol>
# No frames
<stdout nonewline="yes">
</stdout>
# CURLE_RECV_ERROR
<errorcode>
56
</errorcode>
# Strip HTTP header from <protocol>
<strip>
^GET /.*
^(Host|User-Agent|Accept|Upgrade|Connection|Sec-WebSocket-(Version|Key)): .*
^\s*$
</strip>
</verify>
</testcase>

72
tests/data/test2705 Normal file
View file

@ -0,0 +1,72 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
<client>
<name>
ws: Invalid reserved bit RSV3
</name>
<features>
Debug
ws
</features>
<server>
http
</server>
<tool>
lib2700
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
<setenv>
CURL_WS_FORCE_ZERO_MASK=1
</setenv>
</client>
<reply>
<servercmd>
upgrade
</servercmd>
# Full list of frames: see <verify.stdout> below
# An empty frame with the RSV3 bit set
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets
Server: server/%TESTNUMBER
Upgrade: Websocket
Connection: Upgrade
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%91%00]hex%
</data>
</reply>
<verify>
# No frames
<protocol nonewline="yes">
</protocol>
# No frames
<stdout nonewline="yes">
</stdout>
# CURLE_RECV_ERROR
<errorcode>
56
</errorcode>
# Strip HTTP header from <protocol>
<strip>
^GET /.*
^(Host|User-Agent|Accept|Upgrade|Connection|Sec-WebSocket-(Version|Key)): .*
^\s*$
</strip>
</verify>
</testcase>

72
tests/data/test2706 Normal file
View file

@ -0,0 +1,72 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
<client>
<name>
ws: Invalid masked server message
</name>
<features>
Debug
ws
</features>
<server>
http
</server>
<tool>
lib2700
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
<setenv>
CURL_WS_FORCE_ZERO_MASK=1
</setenv>
</client>
<reply>
<servercmd>
upgrade
</servercmd>
# Full list of frames: see <verify.stdout> below
# An empty frame with masking
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets
Server: server/%TESTNUMBER
Upgrade: Websocket
Connection: Upgrade
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%81%80%12%34%56%78]hex%
</data>
</reply>
<verify>
# No frames
<protocol nonewline="yes">
</protocol>
# No frames
<stdout nonewline="yes">
</stdout>
# CURLE_RECV_ERROR
<errorcode>
56
</errorcode>
# Strip HTTP header from <protocol>
<strip>
^GET /.*
^(Host|User-Agent|Accept|Upgrade|Connection|Sec-WebSocket-(Version|Key)): .*
^\s*$
</strip>
</verify>
</testcase>

84
tests/data/test2707 Normal file
View file

@ -0,0 +1,84 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
<client>
<name>
ws: Peculiar frame sizes
</name>
<features>
Debug
ws
</features>
<server>
http
</server>
<tool>
lib2700
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
<setenv>
CURL_WS_FORCE_ZERO_MASK=1
</setenv>
</client>
<reply>
<servercmd>
upgrade
</servercmd>
# Full list of frames: see <verify.stdout> below
# Frames with sizes around special cases of the frame encoding
# see https://datatracker.ietf.org/doc/html/rfc6455#section-5.2
# - 0: empty frame
# - 125: largest payload with 7-bit encoding
# - 126: smallest payload with 16-bit encoding AND this value in first byte indicates 16-bit encoding
# - 127: this value in first byte indicates 64-bit encoding
# - 65535: largest payload with 16-bit length encoding
# - 65536: smallest payload with 64-bit length encoding
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets
Server: server/%TESTNUMBER
Upgrade: Websocket
Connection: Upgrade
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%81%00]hex%%hex[%81%7d]hex%%repeat[125 x _]%%hex[%81%7e%00%7e]hex%%repeat[126 x _]%%hex[%81%7e%00%7f]hex%%repeat[127 x _]%%hex[%81%7e%ff%ff]hex%%repeat[65535 x _]%%hex[%81%7f%00%00%00%00%00%01%00%00]hex%%repeat[65536 x _]%%hex[%88%00]hex%
</data>
</reply>
<verify>
# Exact echo of reply data with additional masking
<protocol nonewline="yes">
%hex[%81%80%00%00%00%00]hex%%hex[%81%fd%00%00%00%00]hex%%repeat[125 x _]%%hex[%81%fe%00%7e%00%00%00%00]hex%%repeat[126 x _]%%hex[%81%fe%00%7f%00%00%00%00]hex%%repeat[127 x _]%%hex[%81%fe%ff%ff%00%00%00%00]hex%%repeat[65535 x _]%%hex[%81%ff%00%00%00%00%00%01%00%00%00%00%00%00]hex%%repeat[65536 x _]%%hex[%88%80%00%00%00%00]hex%
</protocol>
<stdout>
txt fin [0]
txt fin [125] %repeat[125 x _]%
txt fin [126] %repeat[126 x _]%
txt fin [127] %repeat[127 x _]%
txt fin [65535] %repeat[65535 x _]%
txt fin [65536] %repeat[65536 x _]%
close [0]
</stdout>
# CURLE_OK
<errorcode>
0
</errorcode>
# Strip HTTP header from <protocol>
<strip>
^GET /.*
^(Host|User-Agent|Accept|Upgrade|Connection|Sec-WebSocket-(Version|Key)): .*
^\s*$
</strip>
</verify>
</testcase>

75
tests/data/test2708 Normal file
View file

@ -0,0 +1,75 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
<client>
<name>
ws: Automatic PONG
</name>
<features>
Debug
ws
</features>
<server>
http
</server>
<tool>
lib2700
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
<setenv>
CURL_WS_FORCE_ZERO_MASK=1
LIB2700_AUTO_PONG=1
</setenv>
</client>
<reply>
<servercmd>
upgrade
</servercmd>
# PING "test"
# CLOSE
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets
Server: server/%TESTNUMBER
Upgrade: Websocket
Connection: Upgrade
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%89%04test]hex%%hex[%88%00]hex%
</data>
</reply>
<verify>
# PONG "test" (payload MUST equal ping payload)
# see https://datatracker.ietf.org/doc/html/rfc6455#section-5.2
# CLOSE
<protocol nonewline="yes">
%hex[%8A%84%00%00%00%00test%88%80%00%00%00%00]hex%
</protocol>
# PING is handled by lib and never given to application
<stdout>
close [0]
</stdout>
# CURLE_OK
<errorcode>
0
</errorcode>
# Strip HTTP header from <protocol>
<strip>
^GET /.*
^(Host|User-Agent|Accept|Upgrade|Connection|Sec-WebSocket-(Version|Key)): .*
^\s*$
</strip>
</verify>
</testcase>

73
tests/data/test2709 Normal file
View file

@ -0,0 +1,73 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
<client>
<name>
ws: No automatic PONG
</name>
<features>
Debug
ws
</features>
<server>
http
</server>
<tool>
lib2700
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
<setenv>
CURL_WS_FORCE_ZERO_MASK=1
</setenv>
</client>
<reply>
<servercmd>
upgrade
</servercmd>
# PING "test"
# CLOSE
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets
Server: server/%TESTNUMBER
Upgrade: Websocket
Connection: Upgrade
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%89%04test]hex%%hex[%88%00]hex%
</data>
</reply>
<verify>
# Exact echo of reply data with additional masking
<protocol nonewline="yes">
%hex[%89%84%00%00%00%00test]hex%%hex[%88%80%00%00%00%00]hex%
</protocol>
# PING is given to application
<stdout>
ping [4] test
close [0]
</stdout>
# CURLE_OK
<errorcode>
0
</errorcode>
# Strip HTTP header from <protocol>
<strip>
^GET /.*
^(Host|User-Agent|Accept|Upgrade|Connection|Sec-WebSocket-(Version|Key)): .*
^\s*$
</strip>
</verify>
</testcase>

73
tests/data/test2710 Normal file
View file

@ -0,0 +1,73 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
<client>
<name>
ws: Unsolicited PONG
</name>
<features>
Debug
ws
</features>
<server>
http
</server>
<tool>
lib2700
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
<setenv>
CURL_WS_FORCE_ZERO_MASK=1
</setenv>
</client>
<reply>
<servercmd>
upgrade
</servercmd>
# Full list of frames: see <verify.stdout> below
# An unsolicited PONG with and without payload
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets
Server: server/%TESTNUMBER
Upgrade: Websocket
Connection: Upgrade
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%8a%00]hex%%hex[%8a%04pong]hex%%hex[%88%00]hex%
</data>
</reply>
<verify>
# Exact echo of reply data with additional masking
<protocol nonewline="yes">
%hex[%8a%80%00%00%00%00]hex%%hex[%8a%84%00%00%00%00pong]hex%%hex[%88%80%00%00%00%00]hex%
</protocol>
<stdout>
pong [0]
pong [4] pong
close [0]
</stdout>
# CURLE_OK
<errorcode>
0
</errorcode>
# Strip HTTP header from <protocol>
<strip>
^GET /.*
^(Host|User-Agent|Accept|Upgrade|Connection|Sec-WebSocket-(Version|Key)): .*
^\s*$
</strip>
</verify>
</testcase>

74
tests/data/test2711 Normal file
View file

@ -0,0 +1,74 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
<client>
<name>
ws: Empty PING/PONG/CLOSE
</name>
<features>
Debug
ws
</features>
<server>
http
</server>
<tool>
lib2700
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
<setenv>
CURL_WS_FORCE_ZERO_MASK=1
</setenv>
</client>
<reply>
<servercmd>
upgrade
</servercmd>
# Full list of frames: see <verify.stdout> below
# A PING/PONG/CLOSE message without payload
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets
Server: server/%TESTNUMBER
Upgrade: Websocket
Connection: Upgrade
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%89%00]hex%%hex[%8a%00]hex%%hex[%88%00]hex%
</data>
</reply>
<verify>
# Exact echo of reply data with additional masking
<protocol nonewline="yes">
%hex[%89%80%00%00%00%00]hex%%hex[%8a%80%00%00%00%00]hex%%hex[%88%80%00%00%00%00]hex%
</protocol>
# PING is handled by lib and never given to application
<stdout>
ping [0]
pong [0]
close [0]
</stdout>
# CURLE_OK
<errorcode>
0
</errorcode>
# Strip HTTP header from <protocol>
<strip>
^GET /.*
^(Host|User-Agent|Accept|Upgrade|Connection|Sec-WebSocket-(Version|Key)): .*
^\s*$
</strip>
</verify>
</testcase>

74
tests/data/test2712 Normal file
View file

@ -0,0 +1,74 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
<client>
<name>
ws: Max sized PING/PONG/CLOSE
</name>
<features>
Debug
ws
</features>
<server>
http
</server>
<tool>
lib2700
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
<setenv>
CURL_WS_FORCE_ZERO_MASK=1
</setenv>
</client>
<reply>
<servercmd>
upgrade
</servercmd>
# Full list of frames: see <verify.stdout> below
# A PING/PONG/CLOSE with 125 bytes payload each
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets
Server: server/%TESTNUMBER
Upgrade: Websocket
Connection: Upgrade
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%89%7d]hex%%repeat[125 x _]%%hex[%8a%7d]hex%%repeat[125 x _]%%hex[%88%7d%03%e8]hex%%repeat[123 x _]%
</data>
</reply>
<verify>
# Exact echo of reply data with additional masking
<protocol nonewline="yes">
%hex[%89%fd%00%00%00%00]hex%%repeat[125 x _]%%hex[%8a%fd%00%00%00%00]hex%%repeat[125 x _]%%hex[%88%fd%00%00%00%00%03%e8]hex%%repeat[123 x _]%
</protocol>
# PING is handled by lib and never given to application
<stdout>
ping [125] %repeat[125 x _]%
pong [125] %repeat[125 x _]%
close [125] %hex[%03%e8]hex%%repeat[123 x _]%
</stdout>
# CURLE_OK
<errorcode>
0
</errorcode>
# Strip HTTP header from <protocol>
<strip>
^GET /.*
^(Host|User-Agent|Accept|Upgrade|Connection|Sec-WebSocket-(Version|Key)): .*
^\s*$
</strip>
</verify>
</testcase>

72
tests/data/test2713 Normal file
View file

@ -0,0 +1,72 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
<client>
<name>
ws: Invalid oversized PING
</name>
<features>
Debug
ws
</features>
<server>
http
</server>
<tool>
lib2700
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
<setenv>
CURL_WS_FORCE_ZERO_MASK=1
</setenv>
</client>
<reply>
<servercmd>
upgrade
</servercmd>
# Full list of frames: see <verify.stdout> below
# A 126 byte long PING
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets
Server: server/%TESTNUMBER
Upgrade: Websocket
Connection: Upgrade
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%89%7e%00%7e]hex%%repeat[126 x _]%
</data>
</reply>
<verify>
# No frames
<protocol nonewline="yes">
</protocol>
# No frames
<stdout nonewline="yes">
</stdout>
# CURLE_RECV_ERROR
<errorcode>
56
</errorcode>
# Strip HTTP header from <protocol>
<strip>
^GET /.*
^(Host|User-Agent|Accept|Upgrade|Connection|Sec-WebSocket-(Version|Key)): .*
^\s*$
</strip>
</verify>
</testcase>

72
tests/data/test2714 Normal file
View file

@ -0,0 +1,72 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
<client>
<name>
ws: Invalid oversized PONG
</name>
<features>
Debug
ws
</features>
<server>
http
</server>
<tool>
lib2700
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
<setenv>
CURL_WS_FORCE_ZERO_MASK=1
</setenv>
</client>
<reply>
<servercmd>
upgrade
</servercmd>
# Full list of frames: see <verify.stdout> below
# A 126 byte long PONG
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets
Server: server/%TESTNUMBER
Upgrade: Websocket
Connection: Upgrade
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%8a%7e%00%7e]hex%%repeat[126 x _]%
</data>
</reply>
<verify>
# No frames
<protocol nonewline="yes">
</protocol>
# No frames
<stdout nonewline="yes">
</stdout>
# CURLE_RECV_ERROR
<errorcode>
56
</errorcode>
# Strip HTTP header from <protocol>
<strip>
^GET /.*
^(Host|User-Agent|Accept|Upgrade|Connection|Sec-WebSocket-(Version|Key)): .*
^\s*$
</strip>
</verify>
</testcase>

72
tests/data/test2715 Normal file
View file

@ -0,0 +1,72 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
<client>
<name>
ws: Invalid oversized CLOSE
</name>
<features>
Debug
ws
</features>
<server>
http
</server>
<tool>
lib2700
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
<setenv>
CURL_WS_FORCE_ZERO_MASK=1
</setenv>
</client>
<reply>
<servercmd>
upgrade
</servercmd>
# Full list of frames: see <verify.stdout> below
# A 126 byte long CLOSE
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets
Server: server/%TESTNUMBER
Upgrade: Websocket
Connection: Upgrade
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%88%7e%00%7e%03%e8]hex%%repeat[124 x _]%
</data>
</reply>
<verify>
# No frames
<protocol nonewline="yes">
</protocol>
# No frames
<stdout nonewline="yes">
</stdout>
# CURLE_RECV_ERROR
<errorcode>
56
</errorcode>
# Strip HTTP header from <protocol>
<strip>
^GET /.*
^(Host|User-Agent|Accept|Upgrade|Connection|Sec-WebSocket-(Version|Key)): .*
^\s*$
</strip>
</verify>
</testcase>

72
tests/data/test2716 Normal file
View file

@ -0,0 +1,72 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
<client>
<name>
ws: Invalid fragmented PING
</name>
<features>
Debug
ws
</features>
<server>
http
</server>
<tool>
lib2700
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
<setenv>
CURL_WS_FORCE_ZERO_MASK=1
</setenv>
</client>
<reply>
<servercmd>
upgrade
</servercmd>
# Full list of frames: see <verify.stdout> below
# A fragmented PING
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets
Server: server/%TESTNUMBER
Upgrade: Websocket
Connection: Upgrade
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%09%02p1]hex%%hex[%80%02p2]hex%
</data>
</reply>
<verify>
# No frames
<protocol nonewline="yes">
</protocol>
# No frames
<stdout nonewline="yes">
</stdout>
# CURLE_RECV_ERROR
<errorcode>
56
</errorcode>
# Strip HTTP header from <protocol>
<strip>
^GET /.*
^(Host|User-Agent|Accept|Upgrade|Connection|Sec-WebSocket-(Version|Key)): .*
^\s*$
</strip>
</verify>
</testcase>

72
tests/data/test2717 Normal file
View file

@ -0,0 +1,72 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
<client>
<name>
ws: Invalid fragmented PONG
</name>
<features>
Debug
ws
</features>
<server>
http
</server>
<tool>
lib2700
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
<setenv>
CURL_WS_FORCE_ZERO_MASK=1
</setenv>
</client>
<reply>
<servercmd>
upgrade
</servercmd>
# Full list of frames: see <verify.stdout> below
# A fragmented PONG
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets
Server: server/%TESTNUMBER
Upgrade: Websocket
Connection: Upgrade
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%0a%02p1]hex%%hex[%80%02p2]hex%
</data>
</reply>
<verify>
# No frames
<protocol nonewline="yes">
</protocol>
# No frames
<stdout nonewline="yes">
</stdout>
# CURLE_RECV_ERROR
<errorcode>
56
</errorcode>
# Strip HTTP header from <protocol>
<strip>
^GET /.*
^(Host|User-Agent|Accept|Upgrade|Connection|Sec-WebSocket-(Version|Key)): .*
^\s*$
</strip>
</verify>
</testcase>

72
tests/data/test2718 Normal file
View file

@ -0,0 +1,72 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
<client>
<name>
ws: Invalid fragmented CLOSE
</name>
<features>
Debug
ws
</features>
<server>
http
</server>
<tool>
lib2700
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
<setenv>
CURL_WS_FORCE_ZERO_MASK=1
</setenv>
</client>
<reply>
<servercmd>
upgrade
</servercmd>
# Full list of frames: see <verify.stdout> below
# A fragmented CLOSE
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets
Server: server/%TESTNUMBER
Upgrade: Websocket
Connection: Upgrade
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%08%02p1]hex%%hex[%80%02p2]hex%
</data>
</reply>
<verify>
# No frames
<protocol nonewline="yes">
</protocol>
# No frames
<stdout nonewline="yes">
</stdout>
# CURLE_RECV_ERROR
<errorcode>
56
</errorcode>
# Strip HTTP header from <protocol>
<strip>
^GET /.*
^(Host|User-Agent|Accept|Upgrade|Connection|Sec-WebSocket-(Version|Key)): .*
^\s*$
</strip>
</verify>
</testcase>

81
tests/data/test2719 Normal file
View file

@ -0,0 +1,81 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
<client>
<name>
ws: Fragmented messages
</name>
<features>
Debug
ws
</features>
<server>
http
</server>
<tool>
lib2700
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
<setenv>
CURL_WS_FORCE_ZERO_MASK=1
</setenv>
</client>
<reply>
<servercmd>
upgrade
</servercmd>
# Full list of frames: see <verify.stdout> below
# Fragmented TEXT/BINARY messages, each with 2/3 fragments
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets
Server: server/%TESTNUMBER
Upgrade: Websocket
Connection: Upgrade
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%01%02t1]hex%%hex[%80%02t2]hex%%hex[%01%02t1]hex%%hex[%00%02t2]hex%%hex[%80%02t3]hex%%hex[%02%02b1]hex%%hex[%80%02b2]hex%%hex[%02%02b1]hex%%hex[%00%02b2]hex%%hex[%80%02b3]hex%%hex[%88%00]hex%
</data>
</reply>
<verify>
# Exact echo of reply data with additional masking
<protocol nonewline="yes">
%hex[%01%82%00%00%00%00t1]hex%%hex[%80%82%00%00%00%00t2]hex%%hex[%01%82%00%00%00%00t1]hex%%hex[%00%82%00%00%00%00t2]hex%%hex[%80%82%00%00%00%00t3]hex%%hex[%02%82%00%00%00%00b1]hex%%hex[%80%82%00%00%00%00b2]hex%%hex[%02%82%00%00%00%00b1]hex%%hex[%00%82%00%00%00%00b2]hex%%hex[%80%82%00%00%00%00b3]hex%%hex[%88%80%00%00%00%00]hex%
</protocol>
<stdout>
txt --- [2] t1
txt fin [2] t2
txt --- [2] t1
txt --- [2] t2
txt fin [2] t3
bin --- [2] b1
bin fin [2] b2
bin --- [2] b1
bin --- [2] b2
bin fin [2] b3
close [0]
</stdout>
# CURLE_OK
<errorcode>
0
</errorcode>
# Strip HTTP header from <protocol>
<strip>
^GET /.*
^(Host|User-Agent|Accept|Upgrade|Connection|Sec-WebSocket-(Version|Key)): .*
^\s*$
</strip>
</verify>
</testcase>

86
tests/data/test2720 Normal file
View file

@ -0,0 +1,86 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
<client>
<name>
ws: Fragmented messages with empty fragments
</name>
<features>
Debug
ws
</features>
<server>
http
</server>
<tool>
lib2700
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
<setenv>
CURL_WS_FORCE_ZERO_MASK=1
</setenv>
</client>
<reply>
<servercmd>
upgrade
</servercmd>
# Full list of frames: see <verify.stdout> below
# 1st a message with an emtpy fragment at the beginning
# 2nd a message with an emtpy fragment in the middle
# 3rd a message with an emtpy fragment at the end
# 4th a message with only empty fragments
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets
Server: server/%TESTNUMBER
Upgrade: Websocket
Connection: Upgrade
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%01%00]hex%%hex[%00%02a1]hex%%hex[%80%02a2]hex%%hex[%01%02b1]hex%%hex[%00%00]hex%%hex[%80%02b2]hex%%hex[%01%02c1]hex%%hex[%00%02c2]hex%%hex[%80%00]hex%%hex[%01%00]hex%%hex[%00%00]hex%%hex[%80%00]hex%%hex[%88%00]hex%
</data>
</reply>
<verify>
# Exact echo of reply data with additional masking
<protocol nonewline="yes">
%hex[%01%80%00%00%00%00]hex%%hex[%00%82%00%00%00%00a1]hex%%hex[%80%82%00%00%00%00a2]hex%%hex[%01%82%00%00%00%00b1]hex%%hex[%00%80%00%00%00%00]hex%%hex[%80%82%00%00%00%00b2]hex%%hex[%01%82%00%00%00%00c1]hex%%hex[%00%82%00%00%00%00c2]hex%%hex[%80%80%00%00%00%00]hex%%hex[%01%80%00%00%00%00]hex%%hex[%00%80%00%00%00%00]hex%%hex[%80%80%00%00%00%00]hex%%hex[%88%80%00%00%00%00]hex%
</protocol>
<stdout>
txt --- [0]
txt --- [2] a1
txt fin [2] a2
txt --- [2] b1
txt --- [0]
txt fin [2] b2
txt --- [2] c1
txt --- [2] c2
txt fin [0]
txt --- [0]
txt --- [0]
txt fin [0]
close [0]
</stdout>
# CURLE_OK
<errorcode>
0
</errorcode>
# Strip HTTP header from <protocol>
<strip>
^GET /.*
^(Host|User-Agent|Accept|Upgrade|Connection|Sec-WebSocket-(Version|Key)): .*
^\s*$
</strip>
</verify>
</testcase>

77
tests/data/test2721 Normal file
View file

@ -0,0 +1,77 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
<client>
<name>
ws: Fragmented messages with interleaved pong
</name>
<features>
Debug
ws
</features>
<server>
http
</server>
<tool>
lib2700
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
<setenv>
CURL_WS_FORCE_ZERO_MASK=1
</setenv>
</client>
<reply>
<servercmd>
upgrade
</servercmd>
# Full list of frames: see <verify.stdout> below
# A TEXT/BINARY message fragmented into two frames each, with pongs in the middle
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets
Server: server/%TESTNUMBER
Upgrade: Websocket
Connection: Upgrade
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%01%02t1]hex%%hex[%8a%02p1]hex%%hex[%80%02t2]hex%%hex[%02%02b1]hex%%hex[%8a%02p2]hex%%hex[%80%02b2]hex%%hex[%88%00]hex%
</data>
</reply>
<verify>
# Exact echo of reply data with additional masking
<protocol nonewline="yes">
%hex[%01%82%00%00%00%00t1]hex%%hex[%8a%82%00%00%00%00p1]hex%%hex[%80%82%00%00%00%00t2]hex%%hex[%02%82%00%00%00%00b1]hex%%hex[%8a%82%00%00%00%00p2]hex%%hex[%80%82%00%00%00%00b2]hex%%hex[%88%80%00%00%00%00]hex%
</protocol>
<stdout>
txt --- [2] t1
pong [2] p1
txt fin [2] t2
bin --- [2] b1
pong [2] p2
bin fin [2] b2
close [0]
</stdout>
# CURLE_OK
<errorcode>
0
</errorcode>
# Strip HTTP header from <protocol>
<strip>
^GET /.*
^(Host|User-Agent|Accept|Upgrade|Connection|Sec-WebSocket-(Version|Key)): .*
^\s*$
</strip>
</verify>
</testcase>

73
tests/data/test2722 Normal file
View file

@ -0,0 +1,73 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
<client>
<name>
ws: Invalid fragmented message without initial frame
</name>
<features>
Debug
ws
</features>
<server>
http
</server>
<tool>
lib2700
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
<setenv>
CURL_WS_FORCE_ZERO_MASK=1
</setenv>
</client>
<reply>
<servercmd>
upgrade
</servercmd>
# Full list of frames: see <verify.stdout> below
# First a valid BINARY frame
# Second a fragmented message with the first frame missing
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets
Server: server/%TESTNUMBER
Upgrade: Websocket
Connection: Upgrade
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%82%01b]hex%%hex[%00%02m2]hex%%hex[%80%02m3]hex%
</data>
</reply>
<verify>
# Echo of reply data with additional masking up to the missing initial frame
<protocol nonewline="yes">
%hex[%82%81%00%00%00%00b]hex%
</protocol>
# Only frames up to the missing initial frame
<stdout>
bin fin [1] b
</stdout>
# CURLE_RECV_ERROR
<errorcode>
56
</errorcode>
# Strip HTTP header from <protocol>
<strip>
^GET /.*
^(Host|User-Agent|Accept|Upgrade|Connection|Sec-WebSocket-(Version|Key)): .*
^\s*$
</strip>
</verify>
</testcase>

74
tests/data/test2723 Normal file
View file

@ -0,0 +1,74 @@
<testcase>
<info>
<keywords>
WebSockets
</keywords>
</info>
<client>
<name>
ws: Invalid fragmented message without final frame
</name>
<features>
Debug
ws
</features>
<server>
http
</server>
<tool>
lib2700
</tool>
<command>
ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
<setenv>
CURL_WS_FORCE_ZERO_MASK=1
</setenv>
</client>
<reply>
<servercmd>
upgrade
</servercmd>
# Full list of frames: see <verify.stdout> below
# First a fragmented TEXT message with the last frame missing
# Second a valid BINARY frame
<data nocheck="yes" nonewline="yes">
HTTP/1.1 101 Switching to WebSockets
Server: server/%TESTNUMBER
Upgrade: Websocket
Connection: Upgrade
Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
%hex[%01%02t1]hex%%hex[%00%02t2]hex%%hex[%82%01b]hex%
</data>
</reply>
<verify>
# Echo of reply data with additional masking up to the missing final frame
<protocol nonewline="yes">
%hex[%01%82%00%00%00%00t1]hex%%hex[%00%82%00%00%00%00t2]hex%
</protocol>
# Only frames up to the missing final frame
<stdout>
txt --- [2] t1
txt --- [2] t2
</stdout>
# CURLE_RECV_ERROR
<errorcode>
56
</errorcode>
# Strip HTTP header from <protocol>
<strip>
^GET /.*
^(Host|User-Agent|Accept|Upgrade|Connection|Sec-WebSocket-(Version|Key)): .*
^\s*$
</strip>
</verify>
</testcase>