1
0
Fork 0
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:
Andy Green 2014-08-24 14:39:19 +08:00
parent af8db35010
commit 82bac6baec
4 changed files with 66 additions and 10 deletions

View file

@ -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 */

View file

@ -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;

View file

@ -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 {

View file

@ -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)