mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
close should flush any truncated send before really closing
Signed-off-by: Andy Green <andy.green@linaro.org>
This commit is contained in:
parent
d7340c141f
commit
a1a24d26a6
6 changed files with 64 additions and 19 deletions
|
@ -130,8 +130,10 @@ lws_issue_raw_ext_access(struct libwebsocket *wsi,
|
|||
if (eff_buf.token_len) {
|
||||
n = lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
|
||||
eff_buf.token_len);
|
||||
if (n < 0)
|
||||
if (n < 0) {
|
||||
lwsl_info("closing from ext access\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* always either sent it all or privately buffered */
|
||||
}
|
||||
|
|
|
@ -53,13 +53,30 @@ libwebsocket_close_and_free_session(struct libwebsocket_context *context,
|
|||
|
||||
old_state = wsi->state;
|
||||
|
||||
if (old_state == WSI_STATE_DEAD_SOCKET)
|
||||
switch (old_state) {
|
||||
case WSI_STATE_DEAD_SOCKET:
|
||||
return;
|
||||
|
||||
/* we tried the polite way... */
|
||||
if (old_state == WSI_STATE_AWAITING_CLOSE_ACK)
|
||||
case WSI_STATE_AWAITING_CLOSE_ACK:
|
||||
goto just_kill_connection;
|
||||
|
||||
case WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE:
|
||||
if (wsi->truncated_send_len) {
|
||||
libwebsocket_callback_on_writable(context, wsi);
|
||||
return;
|
||||
}
|
||||
lwsl_info("wsi %p completed WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE\n", wsi);
|
||||
goto just_kill_connection;
|
||||
default:
|
||||
if (wsi->truncated_send_len) {
|
||||
lwsl_info("wsi %p entering WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE\n", wsi);
|
||||
wsi->state = WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
wsi->u.ws.close_reason = reason;
|
||||
|
||||
if (wsi->mode == LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT ||
|
||||
|
|
14
lib/output.c
14
lib/output.c
|
@ -99,6 +99,10 @@ int lws_issue_raw(struct libwebsocket *wsi, unsigned char *buf, size_t len)
|
|||
|
||||
if (!len)
|
||||
return 0;
|
||||
/* just ignore sends after we cleared the truncation buffer */
|
||||
if (wsi->state == WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE &&
|
||||
!wsi->truncated_send_len)
|
||||
return len;
|
||||
|
||||
if (wsi->truncated_send_len && (buf < wsi->truncated_send_malloc ||
|
||||
buf > (wsi->truncated_send_malloc +
|
||||
|
@ -149,6 +153,9 @@ handle_truncated_send:
|
|||
lwsl_info("***** %x partial send completed\n", wsi);
|
||||
/* done with it, but don't free it */
|
||||
n = real_len;
|
||||
if (wsi->state == WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE)
|
||||
lwsl_info("***** %x signalling to close now\n", wsi);
|
||||
return -1; /* retry closing now */
|
||||
}
|
||||
/* always callback on writeable */
|
||||
libwebsocket_callback_on_writable(
|
||||
|
@ -480,9 +487,12 @@ LWS_VISIBLE int libwebsockets_serve_http_file_fragment(
|
|||
while (!lws_send_pipe_choked(wsi)) {
|
||||
|
||||
if (wsi->truncated_send_len) {
|
||||
lws_issue_raw(wsi, wsi->truncated_send_malloc +
|
||||
if (lws_issue_raw(wsi, wsi->truncated_send_malloc +
|
||||
wsi->truncated_send_offset,
|
||||
wsi->truncated_send_len);
|
||||
wsi->truncated_send_len) < 0) {
|
||||
lwsl_info("closing from libwebsockets_serve_http_file_fragment\n");
|
||||
return -1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -287,6 +287,7 @@ enum lws_connection_states {
|
|||
WSI_STATE_CLIENT_UNCONNECTED,
|
||||
WSI_STATE_RETURNED_CLOSE_ALREADY,
|
||||
WSI_STATE_AWAITING_CLOSE_ACK,
|
||||
WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE,
|
||||
};
|
||||
|
||||
enum lws_rx_parse_state {
|
||||
|
|
27
lib/server.c
27
lib/server.c
|
@ -506,9 +506,12 @@ int lws_server_socket_service(struct libwebsocket_context *context,
|
|||
|
||||
if (wsi->truncated_send_malloc) {
|
||||
if (pollfd->revents & LWS_POLLOUT)
|
||||
lws_issue_raw(wsi, wsi->truncated_send_malloc +
|
||||
if (lws_issue_raw(wsi, wsi->truncated_send_malloc +
|
||||
wsi->truncated_send_offset,
|
||||
wsi->truncated_send_len);
|
||||
wsi->truncated_send_len) < 0) {
|
||||
lwsl_info("closing from socket service\n");
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* we can't afford to allow input processing send
|
||||
* something new, so spin around he event loop until
|
||||
|
@ -539,16 +542,20 @@ int lws_server_socket_service(struct libwebsocket_context *context,
|
|||
break;
|
||||
}
|
||||
|
||||
/* hm this may want to send (via HTTP callback for example) */
|
||||
/* just ignore incoming if waiting for close */
|
||||
if (wsi->state != WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE) {
|
||||
|
||||
/* hm this may want to send (via HTTP callback for example) */
|
||||
|
||||
n = libwebsocket_read(context, wsi,
|
||||
context->service_buffer, len);
|
||||
if (n < 0)
|
||||
/* we closed wsi */
|
||||
return 0;
|
||||
n = libwebsocket_read(context, wsi,
|
||||
context->service_buffer, len);
|
||||
if (n < 0)
|
||||
/* we closed wsi */
|
||||
return 0;
|
||||
|
||||
/* hum he may have used up the writability above */
|
||||
break;
|
||||
/* hum he may have used up the writability above */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* this handles POLLOUT for http serving fragments */
|
||||
|
|
|
@ -34,9 +34,12 @@ lws_handle_POLLOUT_event(struct libwebsocket_context *context,
|
|||
/* pending truncated sends have uber priority */
|
||||
|
||||
if (wsi->truncated_send_len) {
|
||||
lws_issue_raw(wsi, wsi->truncated_send_malloc +
|
||||
if (lws_issue_raw(wsi, wsi->truncated_send_malloc +
|
||||
wsi->truncated_send_offset,
|
||||
wsi->truncated_send_len);
|
||||
wsi->truncated_send_len) < 0) {
|
||||
lwsl_info("lws_handle_POLLOUT_event signalling to close\n");
|
||||
return -1;
|
||||
}
|
||||
/* leave POLLOUT active either way */
|
||||
return 0;
|
||||
}
|
||||
|
@ -87,8 +90,10 @@ lws_handle_POLLOUT_event(struct libwebsocket_context *context,
|
|||
if (eff_buf.token_len) {
|
||||
n = lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
|
||||
eff_buf.token_len);
|
||||
if (n < 0)
|
||||
if (n < 0) {
|
||||
lwsl_info("closing from POLLOUT spill\n");
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* Keep amount spilled small to minimize chance of this
|
||||
*/
|
||||
|
@ -340,6 +345,8 @@ libwebsocket_service_fd(struct libwebsocket_context *context,
|
|||
case LWS_CONNMODE_SERVER_LISTENER:
|
||||
case LWS_CONNMODE_SSL_ACK_PENDING:
|
||||
n = lws_server_socket_service(context, wsi, pollfd);
|
||||
if (n < 0)
|
||||
goto close_and_handled;
|
||||
goto handled;
|
||||
|
||||
case LWS_CONNMODE_WS_SERVING:
|
||||
|
@ -348,7 +355,8 @@ libwebsocket_service_fd(struct libwebsocket_context *context,
|
|||
/* the guy requested a callback when it was OK to write */
|
||||
|
||||
if ((pollfd->revents & LWS_POLLOUT) &&
|
||||
wsi->state == WSI_STATE_ESTABLISHED &&
|
||||
(wsi->state == WSI_STATE_ESTABLISHED ||
|
||||
wsi->state == WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE) &&
|
||||
lws_handle_POLLOUT_event(context, wsi, pollfd)) {
|
||||
lwsl_info("libwebsocket_service_fd: closing\n");
|
||||
goto close_and_handled;
|
||||
|
|
Loading…
Add table
Reference in a new issue