lws_remove_wsi_from_draining_ext_list(wsi);
if (wsi->state == LWSS_RETURNED_CLOSE_ALREADY ||
+ wsi->state == LWSS_WAITING_TO_SEND_CLOSE_NOTIFICATION ||
wsi->state == LWSS_AWAITING_CLOSE_ACK)
goto already_done;
case LWSS_ESTABLISHED:
case LWSS_AWAITING_CLOSE_ACK:
+ case LWSS_WAITING_TO_SEND_CLOSE_NOTIFICATION:
case LWSS_SHUTDOWN:
if (lws_handshake_client(wsi, &buf, (size_t)len))
goto bail;
return;
/* we tried the polite way... */
+ case LWSS_WAITING_TO_SEND_CLOSE_NOTIFICATION:
case LWSS_AWAITING_CLOSE_ACK:
goto just_kill_connection;
#if defined (LWS_WITH_ESP8266)
wsi->close_is_pending_send_completion = 1;
#endif
- n = lws_write(wsi, &wsi->u.ws.ping_payload_buf[LWS_PRE],
- wsi->u.ws.close_in_ping_buffer_len,
- LWS_WRITE_CLOSE);
- if (n >= 0) {
- /*
- * we have sent a nice protocol level indication we
- * now wish to close, we should not send anything more
- */
- wsi->state = LWSS_AWAITING_CLOSE_ACK;
-
- /*
- * ...and we should wait for a reply for a bit
- * out of politeness
- */
- lws_set_timeout(wsi, PENDING_TIMEOUT_CLOSE_ACK, 1);
- lwsl_debug("sent close indication, awaiting ack\n");
- return;
- }
-
- lwsl_info("close: sending close packet failed, hanging up\n");
+ lwsl_debug("waiting for chance to send close\n");
+ wsi->waiting_to_send_close_frame = 1;
+ wsi->state = LWSS_WAITING_TO_SEND_CLOSE_NOTIFICATION;
+ lws_set_timeout(wsi, PENDING_TIMEOUT_CLOSE_SEND, 2);
+ lws_callback_on_writable(wsi);
- /* else, the send failed and we should just hang up */
+ return;
}
just_kill_connection:
((wsi->state_pre_close == LWSS_ESTABLISHED) ||
(wsi->state_pre_close == LWSS_RETURNED_CLOSE_ALREADY) ||
(wsi->state_pre_close == LWSS_AWAITING_CLOSE_ACK) ||
+ (wsi->state_pre_close == LWSS_WAITING_TO_SEND_CLOSE_NOTIFICATION) ||
(wsi->state_pre_close == LWSS_FLUSHING_STORED_SEND_BEFORE_CLOSE) ||
(wsi->mode == LWSCM_WS_CLIENT && wsi->state_pre_close == LWSS_HTTP) ||
(wsi->mode == LWSCM_WS_SERVING && wsi->state_pre_close == LWSS_HTTP))) {
PENDING_TIMEOUT_AWAITING_SOCKS_CONNECT_REPLY = 20,
PENDING_TIMEOUT_AWAITING_SOCKS_AUTH_REPLY = 21,
PENDING_TIMEOUT_KILLED_BY_SSL_INFO = 22,
+ PENDING_TIMEOUT_KILLED_BY_PARENT = 23,
+ PENDING_TIMEOUT_CLOSE_SEND = 24,
/****** add new things just above ---^ ******/
};
LWSS_ESTABLISHED,
LWSS_CLIENT_HTTP_ESTABLISHED,
LWSS_CLIENT_UNCONNECTED,
+ LWSS_WAITING_TO_SEND_CLOSE_NOTIFICATION,
LWSS_RETURNED_CLOSE_ALREADY,
LWSS_AWAITING_CLOSE_ACK,
LWSS_FLUSHING_STORED_SEND_BEFORE_CLOSE,
unsigned int sending_chunked:1;
unsigned int already_did_cce:1;
unsigned int told_user_closed:1;
+ unsigned int waiting_to_send_close_frame:1;
unsigned int ipv6:1;
#if defined(LWS_WITH_ESP8266)
n = LWS_CALLBACK_HTTP_WRITEABLE;
break;
}
- lwsl_debug("%s: %p (user=%p)\n", __func__, wsi, wsi->user_space);
+
return user_callback_handle_rxflow(wsi->protocol->callback,
wsi, (enum lws_callback_reasons) n,
wsi->user_space, NULL, 0);
}
-int
+LWS_VISIBLE int
lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd)
{
int write_type = LWS_WRITE_PONG;
#endif
int ret, m, n;
- //lwsl_err("%s: %p\n", __func__, wsi);
+// lwsl_err("%s: %p\n", __func__, wsi);
wsi->leave_pollout_active = 0;
wsi->handling_pollout = 1;
#endif
/* Priority 3: pending control packets (pong or close)
+ *
+ * 3a: close notification packet requested from close api
*/
+
+ if (wsi->state == LWSS_WAITING_TO_SEND_CLOSE_NOTIFICATION) {
+ lwsl_debug("sending close packet\n");
+ wsi->waiting_to_send_close_frame = 0;
+ n = lws_write(wsi, &wsi->u.ws.ping_payload_buf[LWS_PRE],
+ wsi->u.ws.close_in_ping_buffer_len,
+ LWS_WRITE_CLOSE);
+ if (n >= 0) {
+ wsi->state = LWSS_AWAITING_CLOSE_ACK;
+ lws_set_timeout(wsi, PENDING_TIMEOUT_CLOSE_ACK, 1);
+ lwsl_debug("sent close indication, awaiting ack\n");
+
+ goto bail_ok;
+ }
+
+ goto bail_die;
+ }
+
+ /* else, the send failed and we should just hang up */
+
if ((wsi->state == LWSS_ESTABLISHED &&
wsi->u.ws.ping_pending_flag) ||
(wsi->state == LWSS_RETURNED_CLOSE_ALREADY &&
wsi->handling_pollout = 0;
/* cannot get leave_pollout_active set after the above */
-
if (!eff && wsi->leave_pollout_active)
/* got set inbetween sampling eff and clearing
* handling_pollout, force POLLOUT on */
/* 1: something requested a callback when it was OK to write */
+ if (wsi->state == LWSS_WAITING_TO_SEND_CLOSE_NOTIFICATION)
+ lwsl_notice("xxx\n");
+
if ((pollfd->revents & LWS_POLLOUT) &&
((wsi->state == LWSS_ESTABLISHED ||
wsi->state == LWSS_HTTP2_ESTABLISHED ||
wsi->state == LWSS_HTTP2_ESTABLISHED_PRE_SETTINGS ||
wsi->state == LWSS_RETURNED_CLOSE_ALREADY ||
+ wsi->state == LWSS_WAITING_TO_SEND_CLOSE_NOTIFICATION ||
wsi->state == LWSS_FLUSHING_STORED_SEND_BEFORE_CLOSE)) &&
lws_handle_POLLOUT_event(wsi, pollfd)) {
if (wsi->state == LWSS_RETURNED_CLOSE_ALREADY)
}
if (wsi->state == LWSS_RETURNED_CLOSE_ALREADY ||
+ wsi->state == LWSS_WAITING_TO_SEND_CLOSE_NOTIFICATION ||
wsi->state == LWSS_AWAITING_CLOSE_ACK) {
/*
* we stopped caring about anything except control