websocket: fix curl_ws_recv()
- when data arrived in several chunks, the collection into the passed buffer always started at offset 0, overwriting the data already there. adding test_20_07 to verify fix - debug environment var CURL_WS_CHUNK_SIZE can be used to influence the buffer chunk size used for en-/decoding. Closes #12945
This commit is contained in:
parent
e3461bbd05
commit
f0c446ab57
@ -116,3 +116,8 @@ Debug-version of the *ntlm-wb* executable.
|
||||
|
||||
OpenLDAP tracing is enabled if this variable exists and its value is 1 or
|
||||
greater. There is a number of debug levels, refer to *openldap.c* comments.
|
||||
|
||||
## CURL_WS_CHUNK_SIZE
|
||||
|
||||
Used to influence the buffer chunk size used for WebSocket encoding and
|
||||
decoding.
|
||||
|
||||
21
lib/ws.c
21
lib/ws.c
@ -754,13 +754,26 @@ CURLcode Curl_ws_accept(struct Curl_easy *data,
|
||||
DEBUGASSERT(data->conn);
|
||||
ws = data->conn->proto.ws;
|
||||
if(!ws) {
|
||||
size_t chunk_size = WS_CHUNK_SIZE;
|
||||
ws = calloc(1, sizeof(*ws));
|
||||
if(!ws)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
data->conn->proto.ws = ws;
|
||||
Curl_bufq_init2(&ws->recvbuf, WS_CHUNK_SIZE, WS_CHUNK_COUNT,
|
||||
#ifdef DEBUGBUILD
|
||||
{
|
||||
char *p = getenv("CURL_WS_CHUNK_SIZE");
|
||||
if(p) {
|
||||
long l = strtol(p, NULL, 10);
|
||||
if(l > 0 && l <= (1*1024*1024)) {
|
||||
chunk_size = (size_t)l;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
DEBUGF(infof(data, "WS, using chunk size %zu", chunk_size));
|
||||
Curl_bufq_init2(&ws->recvbuf, chunk_size, WS_CHUNK_COUNT,
|
||||
BUFQ_OPT_SOFT_LIMIT);
|
||||
Curl_bufq_init2(&ws->sendbuf, WS_CHUNK_SIZE, WS_CHUNK_COUNT,
|
||||
Curl_bufq_init2(&ws->sendbuf, chunk_size, WS_CHUNK_COUNT,
|
||||
BUFQ_OPT_SOFT_LIMIT);
|
||||
ws_dec_init(&ws->dec);
|
||||
ws_enc_init(&ws->enc);
|
||||
@ -834,7 +847,7 @@ CURLcode Curl_ws_accept(struct Curl_easy *data,
|
||||
|
||||
struct ws_collect {
|
||||
struct Curl_easy *data;
|
||||
void *buffer;
|
||||
unsigned char *buffer;
|
||||
size_t buflen;
|
||||
size_t bufidx;
|
||||
int frame_age;
|
||||
@ -886,7 +899,7 @@ static ssize_t ws_client_collect(const unsigned char *buf, size_t buflen,
|
||||
return -1;
|
||||
}
|
||||
*err = CURLE_OK;
|
||||
memcpy(ctx->buffer, buf, nwritten);
|
||||
memcpy(ctx->buffer + ctx->bufidx, buf, nwritten);
|
||||
ctx->bufidx += nwritten;
|
||||
}
|
||||
return nwritten;
|
||||
|
||||
@ -129,3 +129,14 @@ class TestWebsockets:
|
||||
url = f'ws://localhost:{env.ws_port}/'
|
||||
r = client.run(args=[url, str(65535 - 5), str(65535 + 5)])
|
||||
r.check_exit_code(0)
|
||||
|
||||
# the python websocket server does not like 'large' control frames
|
||||
def test_20_07_data_large_small_recv(self, env: Env, ws_echo, repeat):
|
||||
client = LocalClient(env=env, name='ws-data', run_env={
|
||||
'CURL_WS_CHUNK_SIZE': '1024',
|
||||
})
|
||||
if not client.exists():
|
||||
pytest.skip(f'example client not built: {client.name}')
|
||||
url = f'ws://localhost:{env.ws_port}/'
|
||||
r = client.run(args=[url, str(65535 - 5), str(65535 + 5)])
|
||||
r.check_exit_code(0)
|
||||
|
||||
@ -45,10 +45,12 @@ log = logging.getLogger(__name__)
|
||||
class LocalClient:
|
||||
|
||||
def __init__(self, name: str, env: Env, run_dir: Optional[str] = None,
|
||||
timeout: Optional[float] = None):
|
||||
timeout: Optional[float] = None,
|
||||
run_env: Optional[Dict[str,str]] = None):
|
||||
self.name = name
|
||||
self.path = os.path.join(env.project_dir, f'tests/http/clients/{name}')
|
||||
self.env = env
|
||||
self._run_env= run_env
|
||||
self._timeout = timeout if timeout else env.test_timeout
|
||||
self._curl = os.environ['CURL'] if 'CURL' in os.environ else env.curl
|
||||
self._run_dir = run_dir if run_dir else os.path.join(env.gen_dir, name)
|
||||
@ -95,7 +97,7 @@ class LocalClient:
|
||||
with open(self._stderrfile, 'w') as cerr:
|
||||
p = subprocess.run(myargs, stderr=cerr, stdout=cout,
|
||||
cwd=self._run_dir, shell=False,
|
||||
input=None,
|
||||
input=None, env=self._run_env,
|
||||
timeout=self._timeout)
|
||||
exitcode = p.returncode
|
||||
except subprocess.TimeoutExpired:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user