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 */
}
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 ||
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 +
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(
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;
}
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 {
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
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 */
/* 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;
}
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
*/
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:
/* 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;