mirror of
https://github.com/curl/curl.git
synced 2025-02-05 14:30:10 +08:00
ws: fix autoping handling
Reported-by: Alexey Savchuk Fixes #10289 Closes #10294
This commit is contained in:
parent
521da2dbd3
commit
abae4e31a2
73
lib/ws.c
73
lib/ws.c
@ -183,12 +183,12 @@ static void ws_decode_shift(struct Curl_easy *data, size_t spent)
|
|||||||
|
|
||||||
/* ws_decode() decodes a binary frame into structured WebSocket data,
|
/* ws_decode() decodes a binary frame into structured WebSocket data,
|
||||||
|
|
||||||
wpkt - the incoming raw data. If NULL, work on the already buffered data.
|
data - the transfer
|
||||||
ilen - the size of the provided data, perhaps too little, perhaps too much
|
inbuf - incoming raw data. If NULL, work on the already buffered data.
|
||||||
out - stored pointed to extracted data
|
inlen - size of the provided data, perhaps too little, perhaps too much
|
||||||
|
headlen - stored length of the frame header
|
||||||
olen - stored length of the extracted data
|
olen - stored length of the extracted data
|
||||||
oleft - number of unread bytes pending to that belongs to this frame
|
oleft - number of unread bytes pending to that belongs to this frame
|
||||||
more - if there is more data in there
|
|
||||||
flags - stored bitmask about the frame
|
flags - stored bitmask about the frame
|
||||||
|
|
||||||
Returns CURLE_AGAIN if there is only a partial frame in the buffer. Then it
|
Returns CURLE_AGAIN if there is only a partial frame in the buffer. Then it
|
||||||
@ -339,9 +339,6 @@ size_t Curl_ws_writecb(char *buffer, size_t size /* 1 */,
|
|||||||
|
|
||||||
result = ws_decode(data, wsbuf, buflen,
|
result = ws_decode(data, wsbuf, buflen,
|
||||||
&headlen, &write_len, &fb_left, &recvflags);
|
&headlen, &write_len, &fb_left, &recvflags);
|
||||||
consumed += headlen;
|
|
||||||
wsbuf += headlen;
|
|
||||||
buflen -= headlen;
|
|
||||||
if(result == CURLE_AGAIN)
|
if(result == CURLE_AGAIN)
|
||||||
/* insufficient amount of data, keep it for later.
|
/* insufficient amount of data, keep it for later.
|
||||||
* we pretend to have written all since we have a copy */
|
* we pretend to have written all since we have a copy */
|
||||||
@ -350,6 +347,10 @@ size_t Curl_ws_writecb(char *buffer, size_t size /* 1 */,
|
|||||||
infof(data, "WS: decode error %d", (int)result);
|
infof(data, "WS: decode error %d", (int)result);
|
||||||
return nitems - 1;
|
return nitems - 1;
|
||||||
}
|
}
|
||||||
|
consumed += headlen;
|
||||||
|
wsbuf += headlen;
|
||||||
|
buflen -= headlen;
|
||||||
|
|
||||||
/* New frame. store details about the frame to be reachable with
|
/* New frame. store details about the frame to be reachable with
|
||||||
curl_ws_meta() from within the write callback */
|
curl_ws_meta() from within the write callback */
|
||||||
ws->ws.frame.age = 0;
|
ws->ws.frame.age = 0;
|
||||||
@ -392,7 +393,6 @@ size_t Curl_ws_writecb(char *buffer, size_t size /* 1 */,
|
|||||||
return nitems;
|
return nitems;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CURL_EXTERN CURLcode curl_ws_recv(struct Curl_easy *data, void *buffer,
|
CURL_EXTERN CURLcode curl_ws_recv(struct Curl_easy *data, void *buffer,
|
||||||
size_t buflen, size_t *nread,
|
size_t buflen, size_t *nread,
|
||||||
struct curl_ws_frame **metap)
|
struct curl_ws_frame **metap)
|
||||||
@ -409,7 +409,7 @@ CURL_EXTERN CURLcode curl_ws_recv(struct Curl_easy *data, void *buffer,
|
|||||||
return result;
|
return result;
|
||||||
|
|
||||||
while(!done) {
|
while(!done) {
|
||||||
size_t write_len;
|
size_t datalen;
|
||||||
unsigned int recvflags;
|
unsigned int recvflags;
|
||||||
|
|
||||||
if(!wsp->stillblen) {
|
if(!wsp->stillblen) {
|
||||||
@ -433,7 +433,7 @@ CURL_EXTERN CURLcode curl_ws_recv(struct Curl_easy *data, void *buffer,
|
|||||||
curl_off_t oleft;
|
curl_off_t oleft;
|
||||||
/* detect new frame */
|
/* detect new frame */
|
||||||
result = ws_decode(data, (unsigned char *)wsp->stillb, wsp->stillblen,
|
result = ws_decode(data, (unsigned char *)wsp->stillb, wsp->stillblen,
|
||||||
&headlen, &write_len, &oleft, &recvflags);
|
&headlen, &datalen, &oleft, &recvflags);
|
||||||
if(result == CURLE_AGAIN)
|
if(result == CURLE_AGAIN)
|
||||||
/* a packet fragment only */
|
/* a packet fragment only */
|
||||||
break;
|
break;
|
||||||
@ -447,38 +447,45 @@ CURL_EXTERN CURLcode curl_ws_recv(struct Curl_easy *data, void *buffer,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* existing frame, remaining payload handling */
|
/* existing frame, remaining payload handling */
|
||||||
write_len = wsp->frame.bytesleft;
|
datalen = wsp->frame.bytesleft;
|
||||||
if(write_len > wsp->stillblen)
|
if(datalen > wsp->stillblen)
|
||||||
write_len = wsp->stillblen;
|
datalen = wsp->stillblen;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* auto-respond to PINGs */
|
/* auto-respond to PINGs */
|
||||||
if((wsp->frame.flags & CURLWS_PING) && !wsp->frame.bytesleft) {
|
if((wsp->frame.flags & CURLWS_PING) && !wsp->frame.bytesleft) {
|
||||||
infof(data, "WS: auto-respond to PING with a PONG");
|
size_t nsent = 0;
|
||||||
|
infof(data, "WS: auto-respond to PING with a PONG, %zu bytes payload",
|
||||||
|
datalen);
|
||||||
/* send back the exact same content as a PONG */
|
/* send back the exact same content as a PONG */
|
||||||
result = curl_ws_send(data, wsp->stillb, write_len,
|
result = curl_ws_send(data, wsp->stillb, datalen, &nsent, 0,
|
||||||
&write_len, 0, CURLWS_PONG);
|
CURLWS_PONG);
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
infof(data, "WS: bytesleft %zu datalen %zu",
|
||||||
|
wsp->frame.bytesleft, datalen);
|
||||||
|
/* we handled the data part of the PING, advance over that */
|
||||||
|
wsp->stillb += nsent;
|
||||||
|
wsp->stillblen -= nsent;
|
||||||
}
|
}
|
||||||
else if(write_len || !wsp->frame.bytesleft) {
|
else if(datalen) {
|
||||||
if(write_len > buflen)
|
/* there is payload for the user */
|
||||||
write_len = buflen;
|
if(datalen > buflen)
|
||||||
|
datalen = buflen;
|
||||||
/* copy the payload to the user buffer */
|
/* copy the payload to the user buffer */
|
||||||
memcpy(buffer, wsp->stillb, write_len);
|
memcpy(buffer, wsp->stillb, datalen);
|
||||||
*nread = write_len;
|
*nread = datalen;
|
||||||
done = TRUE;
|
done = TRUE;
|
||||||
}
|
|
||||||
if(write_len) {
|
|
||||||
/* update buffer and frame info */
|
/* update buffer and frame info */
|
||||||
wsp->frame.offset += write_len;
|
wsp->frame.offset += datalen;
|
||||||
DEBUGASSERT(wsp->frame.bytesleft >= (curl_off_t)write_len);
|
DEBUGASSERT(wsp->frame.bytesleft >= (curl_off_t)datalen);
|
||||||
if(wsp->frame.bytesleft)
|
if(wsp->frame.bytesleft)
|
||||||
wsp->frame.bytesleft -= write_len;
|
wsp->frame.bytesleft -= datalen;
|
||||||
DEBUGASSERT(write_len <= wsp->stillblen);
|
DEBUGASSERT(datalen <= wsp->stillblen);
|
||||||
wsp->stillblen -= write_len;
|
wsp->stillblen -= datalen;
|
||||||
if(wsp->stillblen)
|
if(wsp->stillblen)
|
||||||
wsp->stillb += write_len;
|
wsp->stillb += datalen;
|
||||||
else
|
else
|
||||||
wsp->stillb = NULL;
|
wsp->stillb = NULL;
|
||||||
}
|
}
|
||||||
@ -686,8 +693,14 @@ CURL_EXTERN CURLcode curl_ws_send(struct Curl_easy *data, const void *buffer,
|
|||||||
|
|
||||||
infof(data, "WS: wanted to send %zu bytes, sent %zu bytes",
|
infof(data, "WS: wanted to send %zu bytes, sent %zu bytes",
|
||||||
headlen + buflen, written);
|
headlen + buflen, written);
|
||||||
*sent = written;
|
|
||||||
|
|
||||||
|
if(!result) {
|
||||||
|
/* the *sent number only counts "payload", excluding the header */
|
||||||
|
if((size_t)written > headlen)
|
||||||
|
*sent = written - headlen;
|
||||||
|
else
|
||||||
|
*sent = 0;
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user