mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
defer PONG send until no partial send buffer
Reported-by: Andrew Canaday Signed-off-by: Andy Green <andy.green@linaro.org>
This commit is contained in:
parent
af8db35010
commit
82bac6baec
4 changed files with 66 additions and 10 deletions
|
@ -224,6 +224,12 @@ just_kill_connection:
|
|||
wsi->truncated_send_malloc = NULL;
|
||||
wsi->truncated_send_len = 0;
|
||||
}
|
||||
if (wsi->u.ws.ping_payload_buf) {
|
||||
free(wsi->u.ws.ping_payload_buf);
|
||||
wsi->u.ws.ping_payload_buf = NULL;
|
||||
wsi->u.ws.ping_payload_alloc = 0;
|
||||
wsi->u.ws.ping_payload_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* tell the user it's all over for this guy */
|
||||
|
|
|
@ -898,16 +898,45 @@ spill:
|
|||
case LWS_WS_OPCODE_07__PING:
|
||||
lwsl_info("received %d byte ping, sending pong\n",
|
||||
wsi->u.ws.rx_user_buffer_head);
|
||||
lwsl_hexdump(&wsi->u.ws.rx_user_buffer[
|
||||
LWS_SEND_BUFFER_PRE_PADDING],
|
||||
wsi->u.ws.rx_user_buffer_head);
|
||||
/* parrot the ping packet payload back as a pong */
|
||||
n = libwebsocket_write(wsi, (unsigned char *)
|
||||
&wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
|
||||
wsi->u.ws.rx_user_buffer_head, LWS_WRITE_PONG);
|
||||
if (n < 0)
|
||||
return -1;
|
||||
/* ... then just drop it */
|
||||
|
||||
if (wsi->u.ws.ping_payload_len) {
|
||||
/*
|
||||
* there is already a pending ping payload
|
||||
* we should just log and drop
|
||||
*/
|
||||
lwsl_parser("DROP PING since one pending\n");
|
||||
goto ping_drop;
|
||||
}
|
||||
|
||||
/* control packets can only be < 128 bytes long */
|
||||
if (wsi->u.ws.ping_payload_len > 128 - 4) {
|
||||
lwsl_parser("DROP PING payload too large\n");
|
||||
goto ping_drop;
|
||||
}
|
||||
|
||||
/* if existing buffer is too small, drop it */
|
||||
if (wsi->u.ws.ping_payload_buf &&
|
||||
wsi->u.ws.ping_payload_alloc < wsi->u.ws.rx_user_buffer_head) {
|
||||
free(wsi->u.ws.ping_payload_buf);
|
||||
wsi->u.ws.ping_payload_buf = NULL;
|
||||
}
|
||||
|
||||
/* if no buffer, allocate it */
|
||||
if (!wsi->u.ws.ping_payload_buf) {
|
||||
wsi->u.ws.ping_payload_buf = malloc(wsi->u.ws.rx_user_buffer_head + LWS_SEND_BUFFER_PRE_PADDING);
|
||||
wsi->u.ws.ping_payload_alloc = wsi->u.ws.rx_user_buffer_head;
|
||||
}
|
||||
|
||||
/* stash the pong payload */
|
||||
memcpy(wsi->u.ws.ping_payload_buf + LWS_SEND_BUFFER_PRE_PADDING,
|
||||
&wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
|
||||
wsi->u.ws.rx_user_buffer_head);
|
||||
|
||||
wsi->u.ws.ping_payload_len = wsi->u.ws.rx_user_buffer_head;
|
||||
|
||||
/* get it sent as soon as possible */
|
||||
libwebsocket_callback_on_writable(wsi->protocol->owning_server, wsi);
|
||||
ping_drop:
|
||||
wsi->u.ws.rx_user_buffer_head = 0;
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -565,6 +565,10 @@ struct _lws_websocket_related {
|
|||
unsigned int this_frame_masked:1;
|
||||
unsigned int inside_frame:1; /* next write will be more of frame */
|
||||
unsigned int clean_buffer:1; /* buffer not rewritten by extension */
|
||||
|
||||
unsigned char *ping_payload_buf; /* non-NULL if malloc'd */
|
||||
unsigned int ping_payload_alloc; /* length malloc'd */
|
||||
unsigned int ping_payload_len; /* nonzero if PONG pending */
|
||||
};
|
||||
|
||||
struct libwebsocket {
|
||||
|
|
|
@ -48,7 +48,24 @@ lws_handle_POLLOUT_event(struct libwebsocket_context *context,
|
|||
return -1; /* retry closing now */
|
||||
}
|
||||
|
||||
/* pending control packets have next priority */
|
||||
|
||||
if (wsi->u.ws.ping_payload_len) {
|
||||
n = libwebsocket_write(wsi,
|
||||
&wsi->u.ws.ping_payload_buf[
|
||||
LWS_SEND_BUFFER_PRE_PADDING],
|
||||
wsi->u.ws.ping_payload_len,
|
||||
LWS_WRITE_PONG);
|
||||
if (n < 0)
|
||||
return -1;
|
||||
/* well he is sent, mark him done */
|
||||
wsi->u.ws.ping_payload_len = 0;
|
||||
/* leave POLLOUT active either way */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if nothing critical, user can get the callback */
|
||||
|
||||
m = lws_ext_callback_for_each_active(wsi, LWS_EXT_CALLBACK_IS_WRITEABLE,
|
||||
NULL, 0);
|
||||
if (handled == 1)
|
||||
|
|
Loading…
Add table
Reference in a new issue