• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  */
24 
25 #include "private-lib-core.h"
26 
27 #if defined(LWS_WITH_CLIENT)
28 static int
lws_close_trans_q_leader(struct lws_dll2 * d,void * user)29 lws_close_trans_q_leader(struct lws_dll2 *d, void *user)
30 {
31 	struct lws *w = lws_container_of(d, struct lws, dll2_cli_txn_queue);
32 
33 	__lws_close_free_wsi(w, (enum lws_close_status)-1, "trans q leader closing");
34 
35 	return 0;
36 }
37 #endif
38 
39 void
__lws_reset_wsi(struct lws * wsi)40 __lws_reset_wsi(struct lws *wsi)
41 {
42 	if (!wsi)
43 		return;
44 
45 #if defined(LWS_WITH_CLIENT)
46 
47 	lws_free_set_NULL(wsi->cli_hostname_copy);
48 
49 #if defined(LWS_WITH_CONMON)
50 
51 	if (wsi->conmon.dns_results_copy) {
52 		lws_conmon_addrinfo_destroy(wsi->conmon.dns_results_copy);
53 		wsi->conmon.dns_results_copy = NULL;
54 	}
55 
56 	wsi->conmon.ciu_dns =
57 		wsi->conmon.ciu_sockconn =
58 		wsi->conmon.ciu_tls =
59 		wsi->conmon.ciu_txn_resp = 0;
60 #endif
61 
62 	/*
63 	 * if we have wsi in our transaction queue, if we are closing we
64 	 * must go through and close all those first
65 	 */
66 	if (wsi->a.vhost) {
67 
68 		/* we are no longer an active client connection that can piggyback */
69 		lws_dll2_remove(&wsi->dll_cli_active_conns);
70 
71 		lws_dll2_foreach_safe(&wsi->dll2_cli_txn_queue_owner, NULL,
72 				      lws_close_trans_q_leader);
73 
74 		/*
75 		 * !!! If we are closing, but we have pending pipelined
76 		 * transaction results we already sent headers for, that's going
77 		 * to destroy sync for HTTP/1 and leave H2 stream with no live
78 		 * swsi.`
79 		 *
80 		 * However this is normal if we are being closed because the
81 		 * transaction queue leader is closing.
82 		 */
83 		lws_dll2_remove(&wsi->dll2_cli_txn_queue);
84 	}
85 #endif
86 
87 	if (wsi->a.vhost) {
88 		lws_vhost_lock(wsi->a.vhost);
89 		lws_dll2_remove(&wsi->vh_awaiting_socket);
90 		lws_vhost_unlock(wsi->a.vhost);
91 	}
92 
93 	/*
94 	 * Protocol user data may be allocated either internally by lws
95 	 * or by specified the user. We should only free what we allocated.
96 	 */
97 	if (wsi->a.protocol && wsi->a.protocol->per_session_data_size &&
98 	    wsi->user_space && !wsi->user_space_externally_allocated) {
99 		/* confirm no sul left scheduled in user data itself */
100 		lws_sul_debug_zombies(wsi->a.context, wsi->user_space,
101 				wsi->a.protocol->per_session_data_size, __func__);
102 		lws_free_set_NULL(wsi->user_space);
103 	}
104 
105 	/*
106 	 * Don't let buflist content or state from the wsi's previous life
107 	 * carry over to the new life
108 	 */
109 
110 	lws_buflist_destroy_all_segments(&wsi->buflist);
111 	lws_dll2_remove(&wsi->dll_buflist);
112 	lws_buflist_destroy_all_segments(&wsi->buflist_out);
113 #if defined(LWS_WITH_UDP)
114 	if (wsi->udp) {
115 		/* confirm no sul left scheduled in wsi->udp itself */
116 		lws_sul_debug_zombies(wsi->a.context, wsi->udp,
117 				      sizeof(*wsi->udp), "close udp wsi");
118 		lws_free_set_NULL(wsi->udp);
119 	}
120 #endif
121 	wsi->retry = 0;
122 
123 #if defined(LWS_WITH_CLIENT)
124 	lws_dll2_remove(&wsi->dll2_cli_txn_queue);
125 	lws_dll2_remove(&wsi->dll_cli_active_conns);
126 	if (wsi->cli_hostname_copy)
127 		lws_free_set_NULL(wsi->cli_hostname_copy);
128 #endif
129 
130 #if defined(LWS_WITH_SYS_ASYNC_DNS)
131 	lws_async_dns_cancel(wsi);
132 #endif
133 
134 #if defined(LWS_WITH_HTTP_PROXY)
135 	if (wsi->http.buflist_post_body)
136 		lws_buflist_destroy_all_segments(&wsi->http.buflist_post_body);
137 #endif
138 
139 #if defined(LWS_WITH_SERVER)
140 	lws_dll2_remove(&wsi->listen_list);
141 #endif
142 
143 #if defined(LWS_WITH_CLIENT)
144 	if (wsi->a.vhost)
145 		lws_dll2_remove(&wsi->dll_cli_active_conns);
146 #endif
147 
148 	__lws_same_vh_protocol_remove(wsi);
149 #if defined(LWS_WITH_CLIENT)
150 	//lws_free_set_NULL(wsi->stash);
151 	lws_free_set_NULL(wsi->cli_hostname_copy);
152 #endif
153 
154 #if defined(LWS_WITH_PEER_LIMITS)
155 	lws_peer_track_wsi_close(wsi->a.context, wsi->peer);
156 	wsi->peer = NULL;
157 #endif
158 
159 	/* since we will destroy the wsi, make absolutely sure now */
160 
161 #if defined(LWS_WITH_OPENSSL)
162 	__lws_ssl_remove_wsi_from_buffered_list(wsi);
163 #endif
164 	__lws_wsi_remove_from_sul(wsi);
165 
166 	if (lws_rops_fidx(wsi->role_ops, LWS_ROPS_destroy_role))
167 		lws_rops_func_fidx(wsi->role_ops,
168 				   LWS_ROPS_destroy_role).destroy_role(wsi);
169 
170 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
171 	__lws_header_table_detach(wsi, 0);
172 #endif
173 
174 #if defined(LWS_ROLE_H2)
175 	/*
176 	 * Let's try to clean out the h2-ness of the wsi
177 	 */
178 
179 	memset(&wsi->h2, 0, sizeof(wsi->h2));
180 
181 	wsi->hdr_parsing_completed = wsi->mux_substream =
182 	wsi->upgraded_to_http2 = wsi->mux_stream_immortal =
183 	wsi->h2_acked_settings = wsi->seen_nonpseudoheader =
184 	wsi->socket_is_permanently_unusable = wsi->favoured_pollin =
185 	wsi->already_did_cce = wsi->told_user_closed =
186 	wsi->waiting_to_send_close_frame = wsi->close_needs_ack =
187 	wsi->parent_pending_cb_on_writable = wsi->seen_zero_length_recv =
188 	wsi->close_when_buffered_out_drained = wsi->could_have_pending = 0;
189 #endif
190 
191 #if defined(LWS_WITH_CLIENT)
192 	wsi->do_ws = wsi->chunked = wsi->client_rx_avail =
193 	wsi->client_http_body_pending = wsi->transaction_from_pipeline_queue =
194 	wsi->keepalive_active = wsi->keepalive_rejected =
195 	wsi->redirected_to_get = wsi->client_pipeline = wsi->client_h2_alpn =
196 	wsi->client_mux_substream = wsi->client_mux_migrated =
197 	wsi->tls_session_reused = wsi->perf_done = 0;
198 
199 	wsi->immortal_substream_count = 0;
200 #endif
201 }
202 
203 /* req cx lock */
204 
205 void
__lws_free_wsi(struct lws * wsi)206 __lws_free_wsi(struct lws *wsi)
207 {
208 	struct lws_vhost *vh;
209 
210 	if (!wsi)
211 		return;
212 
213 	lws_context_assert_lock_held(wsi->a.context);
214 
215 #if defined(LWS_WITH_SECURE_STREAMS)
216 	if (wsi->for_ss) {
217 
218 #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
219 		if (wsi->client_bound_sspc) {
220 			lws_sspc_handle_t *h = (lws_sspc_handle_t *)
221 							wsi->a.opaque_user_data;
222 			if (h) {
223 				h->cwsi = NULL;
224 				wsi->a.opaque_user_data = NULL;
225 			}
226 		} else
227 #endif
228 		{
229 			/*
230 			 * Make certain it is disconnected from the ss by now
231 			 */
232 			lws_ss_handle_t *h = (lws_ss_handle_t *)
233 							wsi->a.opaque_user_data;
234 
235 			if (h) {
236 				h->wsi = NULL;
237 				wsi->a.opaque_user_data = NULL;
238 			}
239 		}
240 	}
241 #endif
242 
243 	vh = wsi->a.vhost;
244 
245 	__lws_reset_wsi(wsi);
246 	__lws_wsi_remove_from_sul(wsi);
247 
248 	if (vh)
249 		/* this may destroy vh */
250 		__lws_vhost_unbind_wsi(wsi); /* req cx + vh lock */
251 
252 #if defined(LWS_WITH_CLIENT)
253 	if (wsi->stash)
254 		lws_free_set_NULL(wsi->stash);
255 #endif
256 
257 	if (wsi->a.context->event_loop_ops->destroy_wsi)
258 		wsi->a.context->event_loop_ops->destroy_wsi(wsi);
259 
260 	lwsl_wsi_debug(wsi, "tsi fds count %d\n",
261 			wsi->a.context->pt[(int)wsi->tsi].fds_count);
262 
263 	/* confirm no sul left scheduled in wsi itself */
264 	lws_sul_debug_zombies(wsi->a.context, wsi, sizeof(*wsi), __func__);
265 
266 	__lws_lc_untag(wsi->a.context, &wsi->lc);
267 	lws_free(wsi);
268 }
269 
270 
271 void
lws_remove_child_from_any_parent(struct lws * wsi)272 lws_remove_child_from_any_parent(struct lws *wsi)
273 {
274 	struct lws **pwsi;
275 	int seen = 0;
276 
277 	if (!wsi->parent)
278 		return;
279 
280 	/* detach ourselves from parent's child list */
281 	pwsi = &wsi->parent->child_list;
282 	while (*pwsi) {
283 		if (*pwsi == wsi) {
284 			lwsl_wsi_info(wsi, "detach from parent %s",
285 					    lws_wsi_tag(wsi->parent));
286 
287 			if (wsi->parent->a.protocol)
288 				wsi->parent->a.protocol->callback(wsi,
289 						LWS_CALLBACK_CHILD_CLOSING,
290 					       wsi->parent->user_space, wsi, 0);
291 
292 			*pwsi = wsi->sibling_list;
293 			seen = 1;
294 			break;
295 		}
296 		pwsi = &(*pwsi)->sibling_list;
297 	}
298 	if (!seen)
299 		lwsl_wsi_err(wsi, "failed to detach from parent");
300 
301 	wsi->parent = NULL;
302 }
303 
304 #if defined(LWS_WITH_CLIENT)
305 void
lws_inform_client_conn_fail(struct lws * wsi,void * arg,size_t len)306 lws_inform_client_conn_fail(struct lws *wsi, void *arg, size_t len)
307 {
308 	lws_addrinfo_clean(wsi);
309 
310 	if (wsi->already_did_cce)
311 		return;
312 
313 	wsi->already_did_cce = 1;
314 
315 	if (!wsi->a.protocol)
316 		return;
317 
318 	if (!wsi->client_suppress_CONNECTION_ERROR)
319 		wsi->a.protocol->callback(wsi,
320 					LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
321 					wsi->user_space, arg, len);
322 }
323 #endif
324 
325 void
lws_addrinfo_clean(struct lws * wsi)326 lws_addrinfo_clean(struct lws *wsi)
327 {
328 #if defined(LWS_WITH_CLIENT)
329 	struct lws_dll2 *d = lws_dll2_get_head(&wsi->dns_sorted_list), *d1;
330 
331 	while (d) {
332 		lws_dns_sort_t *r = lws_container_of(d, lws_dns_sort_t, list);
333 
334 		d1 = d->next;
335 		lws_dll2_remove(d);
336 		lws_free(r);
337 
338 		d = d1;
339 	}
340 #endif
341 }
342 
343 /* requires cx and pt lock */
344 
345 void
__lws_close_free_wsi(struct lws * wsi,enum lws_close_status reason,const char * caller)346 __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason,
347 		     const char *caller)
348 {
349 	struct lws_context_per_thread *pt;
350 	const struct lws_protocols *pro;
351 	struct lws_context *context;
352 	struct lws *wsi1, *wsi2;
353 	int n, ccb;
354 
355 	if (!wsi)
356 		return;
357 
358 	lwsl_wsi_info(wsi, "caller: %s", caller);
359 
360 	lws_access_log(wsi);
361 
362 	if (!lws_dll2_is_detached(&wsi->dll_buflist))
363 		lwsl_wsi_info(wsi, "going down with stuff in buflist");
364 
365 	context = wsi->a.context;
366 	pt = &context->pt[(int)wsi->tsi];
367 
368 	if (pt->pipe_wsi == wsi)
369 		pt->pipe_wsi = NULL;
370 
371 #if defined(LWS_WITH_SYS_METRICS) && \
372     (defined(LWS_WITH_CLIENT) || defined(LWS_WITH_SERVER))
373 	/* wsi level: only reports if dangling caliper */
374 	if (wsi->cal_conn.mt && wsi->cal_conn.us_start) {
375 		if ((lws_metrics_priv_to_pub(wsi->cal_conn.mt)->flags) & LWSMTFL_REPORT_HIST) {
376 			lws_metrics_caliper_report_hist(wsi->cal_conn, (struct lws *)NULL);
377 		} else {
378 			lws_metrics_caliper_report(wsi->cal_conn, METRES_NOGO);
379 			lws_metrics_caliper_done(wsi->cal_conn);
380 		}
381 	} else
382 		lws_metrics_caliper_done(wsi->cal_conn);
383 #endif
384 
385 #if defined(LWS_WITH_SYS_ASYNC_DNS)
386 	if (wsi == context->async_dns.wsi)
387 		context->async_dns.wsi = NULL;
388 #endif
389 
390 	lws_pt_assert_lock_held(pt);
391 
392 #if defined(LWS_WITH_CLIENT)
393 
394 	lws_free_set_NULL(wsi->cli_hostname_copy);
395 	wsi->client_mux_substream_was = wsi->client_mux_substream;
396 
397 	lws_addrinfo_clean(wsi);
398 #endif
399 
400 #if defined(LWS_WITH_HTTP2)
401 	if (wsi->mux_stream_immortal)
402 		lws_http_close_immortal(wsi);
403 #endif
404 
405 	/* if we have children, close them first */
406 	if (wsi->child_list) {
407 		wsi2 = wsi->child_list;
408 		while (wsi2) {
409 			wsi1 = wsi2->sibling_list;
410 //			wsi2->parent = NULL;
411 			/* stop it doing shutdown processing */
412 			wsi2->socket_is_permanently_unusable = 1;
413 			__lws_close_free_wsi(wsi2, reason,
414 					     "general child recurse");
415 			wsi2 = wsi1;
416 		}
417 		wsi->child_list = NULL;
418 	}
419 
420 #if defined(LWS_ROLE_RAW_FILE)
421 	if (wsi->role_ops == &role_ops_raw_file) {
422 		lws_remove_child_from_any_parent(wsi);
423 		__remove_wsi_socket_from_fds(wsi);
424 		if (wsi->a.protocol)
425 			wsi->a.protocol->callback(wsi, wsi->role_ops->close_cb[0],
426 					wsi->user_space, NULL, 0);
427 		goto async_close;
428 	}
429 #endif
430 
431 	wsi->wsistate_pre_close = wsi->wsistate;
432 
433 #ifdef LWS_WITH_CGI
434 	if (wsi->role_ops == &role_ops_cgi) {
435 
436 		// lwsl_debug("%s: closing stdwsi index %d\n", __func__, (int)wsi->lsp_channel);
437 
438 		/* we are not a network connection, but a handler for CGI io */
439 		if (wsi->parent && wsi->parent->http.cgi) {
440 
441 			/*
442 			 * We need to keep the logical cgi around so we can
443 			 * drain it
444 			 */
445 
446 //			if (wsi->parent->child_list == wsi && !wsi->sibling_list)
447 //				lws_cgi_remove_and_kill(wsi->parent);
448 
449 			/* end the binding between us and network connection */
450 			if (wsi->parent->http.cgi && wsi->parent->http.cgi->lsp)
451 				wsi->parent->http.cgi->lsp->stdwsi[(int)wsi->lsp_channel] =
452 									NULL;
453 		}
454 		wsi->socket_is_permanently_unusable = 1;
455 
456 		goto just_kill_connection;
457 	}
458 
459 	if (wsi->http.cgi)
460 		lws_cgi_remove_and_kill(wsi);
461 #endif
462 
463 #if defined(LWS_WITH_CLIENT)
464 	if (!wsi->close_is_redirect)
465 		lws_free_set_NULL(wsi->stash);
466 #endif
467 
468 	if (wsi->role_ops == &role_ops_raw_skt) {
469 		wsi->socket_is_permanently_unusable = 1;
470 		goto just_kill_connection;
471 	}
472 #if defined(LWS_WITH_FILE_OPS) && (defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2))
473 	if (lwsi_role_http(wsi) && lwsi_role_server(wsi) &&
474 	    wsi->http.fop_fd != NULL)
475 		lws_vfs_file_close(&wsi->http.fop_fd);
476 #endif
477 
478 	if (lwsi_state(wsi) == LRS_DEAD_SOCKET)
479 		return;
480 
481 	if (wsi->socket_is_permanently_unusable ||
482 	    reason == LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY ||
483 	    lwsi_state(wsi) == LRS_SHUTDOWN)
484 		goto just_kill_connection;
485 
486 	switch (lwsi_state_PRE_CLOSE(wsi)) {
487 	case LRS_DEAD_SOCKET:
488 		return;
489 
490 	/* we tried the polite way... */
491 	case LRS_WAITING_TO_SEND_CLOSE:
492 	case LRS_AWAITING_CLOSE_ACK:
493 	case LRS_RETURNED_CLOSE:
494 		goto just_kill_connection;
495 
496 	case LRS_FLUSHING_BEFORE_CLOSE:
497 		if (lws_has_buffered_out(wsi)
498 #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
499 		    || wsi->http.comp_ctx.buflist_comp ||
500 		    wsi->http.comp_ctx.may_have_more
501 #endif
502 		 ) {
503 			lws_callback_on_writable(wsi);
504 			return;
505 		}
506 		lwsl_wsi_info(wsi, " end LRS_FLUSHING_BEFORE_CLOSE");
507 		goto just_kill_connection;
508 	default:
509 		if (lws_has_buffered_out(wsi)
510 #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
511 				|| wsi->http.comp_ctx.buflist_comp ||
512 		    wsi->http.comp_ctx.may_have_more
513 #endif
514 		) {
515 			lwsl_wsi_info(wsi, "LRS_FLUSHING_BEFORE_CLOSE");
516 			lwsi_set_state(wsi, LRS_FLUSHING_BEFORE_CLOSE);
517 			__lws_set_timeout(wsi,
518 				PENDING_FLUSH_STORED_SEND_BEFORE_CLOSE, 5);
519 			return;
520 		}
521 		break;
522 	}
523 
524 	if (lwsi_state(wsi) == LRS_WAITING_CONNECT ||
525 	    lwsi_state(wsi) == LRS_WAITING_DNS ||
526 	    lwsi_state(wsi) == LRS_H1C_ISSUE_HANDSHAKE)
527 		goto just_kill_connection;
528 
529 	if (!wsi->told_user_closed && wsi->user_space && wsi->a.protocol &&
530 	    wsi->protocol_bind_balance) {
531 		wsi->a.protocol->callback(wsi,
532 				wsi->role_ops->protocol_unbind_cb[
533 				       !!lwsi_role_server(wsi)],
534 				       wsi->user_space, (void *)__func__, 0);
535 		wsi->protocol_bind_balance = 0;
536 	}
537 
538 	/*
539 	 * signal we are closing, lws_write will
540 	 * add any necessary version-specific stuff.  If the write fails,
541 	 * no worries we are closing anyway.  If we didn't initiate this
542 	 * close, then our state has been changed to
543 	 * LRS_RETURNED_CLOSE and we will skip this.
544 	 *
545 	 * Likewise if it's a second call to close this connection after we
546 	 * sent the close indication to the peer already, we are in state
547 	 * LRS_AWAITING_CLOSE_ACK and will skip doing this a second time.
548 	 */
549 
550 	if (lws_rops_fidx(wsi->role_ops, LWS_ROPS_close_via_role_protocol) &&
551 	    lws_rops_func_fidx(wsi->role_ops, LWS_ROPS_close_via_role_protocol).
552 					 close_via_role_protocol(wsi, reason)) {
553 		lwsl_wsi_info(wsi, "close_via_role took over (sockfd %d)",
554 			      wsi->desc.sockfd);
555 		return;
556 	}
557 
558 just_kill_connection:
559 
560 	lwsl_wsi_debug(wsi, "real just_kill_connection A: (sockfd %d)",
561 			wsi->desc.sockfd);
562 
563 #if defined(LWS_WITH_THREADPOOL)
564 	lws_threadpool_wsi_closing(wsi);
565 #endif
566 
567 #if defined(LWS_WITH_FILE_OPS) && (defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2))
568 	if (lwsi_role_http(wsi) && lwsi_role_server(wsi) &&
569 	    wsi->http.fop_fd != NULL)
570 		lws_vfs_file_close(&wsi->http.fop_fd);
571 #endif
572 
573 	lws_sul_cancel(&wsi->sul_connect_timeout);
574 #if defined(LWS_WITH_SYS_ASYNC_DNS)
575 	lws_async_dns_cancel(wsi);
576 #endif
577 
578 #if defined(LWS_WITH_HTTP_PROXY)
579 	if (wsi->http.buflist_post_body)
580 		lws_buflist_destroy_all_segments(&wsi->http.buflist_post_body);
581 #endif
582 #if defined(LWS_WITH_UDP)
583 	if (wsi->udp) {
584 		/* confirm no sul left scheduled in wsi->udp itself */
585 		lws_sul_debug_zombies(wsi->a.context, wsi->udp,
586 					sizeof(*wsi->udp), "close udp wsi");
587 
588 		lws_free_set_NULL(wsi->udp);
589 	}
590 #endif
591 
592 	if (lws_rops_fidx(wsi->role_ops, LWS_ROPS_close_kill_connection))
593 		lws_rops_func_fidx(wsi->role_ops,
594 				   LWS_ROPS_close_kill_connection).
595 					    close_kill_connection(wsi, reason);
596 
597 	n = 0;
598 
599 	if (!wsi->told_user_closed && wsi->user_space &&
600 	    wsi->protocol_bind_balance && wsi->a.protocol) {
601 		lwsl_debug("%s: %s: DROP_PROTOCOL %s\n", __func__, lws_wsi_tag(wsi),
602 			   wsi->a.protocol ? wsi->a.protocol->name: "NULL");
603 		if (wsi->a.protocol)
604 			wsi->a.protocol->callback(wsi,
605 				wsi->role_ops->protocol_unbind_cb[
606 				       !!lwsi_role_server(wsi)],
607 				       wsi->user_space, (void *)__func__, 0);
608 		wsi->protocol_bind_balance = 0;
609 	}
610 
611 #if defined(LWS_WITH_CLIENT)
612 	if ((
613 #if defined(LWS_ROLE_WS)
614 		/*
615 		 * If our goal is a ws upgrade, effectively we did not reach
616 		 * ESTABLISHED if we did not get the upgrade server reply
617 		 */
618 		(lwsi_state(wsi) == LRS_WAITING_SERVER_REPLY &&
619 		 wsi->role_ops == &role_ops_ws) ||
620 #endif
621 	     lwsi_state(wsi) == LRS_WAITING_DNS ||
622 	     lwsi_state(wsi) == LRS_WAITING_CONNECT) &&
623 	     !wsi->already_did_cce && wsi->a.protocol &&
624 	     !wsi->close_is_redirect) {
625 		static const char _reason[] = "closed before established";
626 
627 		lwsl_wsi_debug(wsi, "closing in unestablished state 0x%x",
628 				lwsi_state(wsi));
629 		wsi->socket_is_permanently_unusable = 1;
630 
631 		lws_inform_client_conn_fail(wsi,
632 			(void *)_reason, sizeof(_reason));
633 	}
634 #endif
635 
636 	/*
637 	 * Testing with ab shows that we have to stage the socket close when
638 	 * the system is under stress... shutdown any further TX, change the
639 	 * state to one that won't emit anything more, and wait with a timeout
640 	 * for the POLLIN to show a zero-size rx before coming back and doing
641 	 * the actual close.
642 	 */
643 	if (wsi->role_ops != &role_ops_raw_skt && !lwsi_role_client(wsi) &&
644 	    lwsi_state(wsi) != LRS_SHUTDOWN &&
645 	    lwsi_state(wsi) != LRS_UNCONNECTED &&
646 	    reason != LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY &&
647 	    !wsi->socket_is_permanently_unusable) {
648 
649 #if defined(LWS_WITH_TLS)
650 		if (lws_is_ssl(wsi) && wsi->tls.ssl) {
651 			n = 0;
652 			switch (__lws_tls_shutdown(wsi)) {
653 			case LWS_SSL_CAPABLE_DONE:
654 			case LWS_SSL_CAPABLE_ERROR:
655 			case LWS_SSL_CAPABLE_MORE_SERVICE_READ:
656 			case LWS_SSL_CAPABLE_MORE_SERVICE_WRITE:
657 			case LWS_SSL_CAPABLE_MORE_SERVICE:
658 				break;
659 			}
660 		} else
661 #endif
662 		{
663 			lwsl_info("%s: shutdown conn: %s (sk %d, state 0x%x)\n",
664 				  __func__, lws_wsi_tag(wsi), (int)(lws_intptr_t)wsi->desc.sockfd,
665 				  lwsi_state(wsi));
666 			if (!wsi->socket_is_permanently_unusable &&
667 			    lws_socket_is_valid(wsi->desc.sockfd)) {
668 				wsi->socket_is_permanently_unusable = 1;
669 				n = shutdown(wsi->desc.sockfd, SHUT_WR);
670 			}
671 		}
672 		if (n)
673 			lwsl_wsi_debug(wsi, "closing: shutdown (state 0x%x) ret %d",
674 				   lwsi_state(wsi), LWS_ERRNO);
675 
676 		/*
677 		 * This causes problems on WINCE / ESP32 with disconnection
678 		 * when the events are half closing connection
679 		 */
680 #if !defined(_WIN32_WCE) && !defined(LWS_PLAT_FREERTOS)
681 		/* libuv: no event available to guarantee completion */
682 		if (!wsi->socket_is_permanently_unusable &&
683 #if defined(LWS_WITH_CLIENT)
684 		    !wsi->close_is_redirect &&
685 #endif
686 		    lws_socket_is_valid(wsi->desc.sockfd) &&
687 		    lwsi_state(wsi) != LRS_SHUTDOWN &&
688 		    (context->event_loop_ops->flags & LELOF_ISPOLL)) {
689 			__lws_change_pollfd(wsi, LWS_POLLOUT, LWS_POLLIN);
690 			lwsi_set_state(wsi, LRS_SHUTDOWN);
691 			__lws_set_timeout(wsi, PENDING_TIMEOUT_SHUTDOWN_FLUSH,
692 					  (int)context->timeout_secs);
693 
694 			return;
695 		}
696 #endif
697 	}
698 
699 	lwsl_wsi_info(wsi, "real just_kill_connection: sockfd %d\n",
700 			wsi->desc.sockfd);
701 
702 #ifdef LWS_WITH_HUBBUB
703 	if (wsi->http.rw) {
704 		lws_rewrite_destroy(wsi->http.rw);
705 		wsi->http.rw = NULL;
706 	}
707 #endif
708 
709 	if (wsi->http.pending_return_headers)
710 		lws_free_set_NULL(wsi->http.pending_return_headers);
711 
712 	/*
713 	 * we won't be servicing or receiving anything further from this guy
714 	 * delete socket from the internal poll list if still present
715 	 */
716 	__lws_ssl_remove_wsi_from_buffered_list(wsi);
717 	__lws_wsi_remove_from_sul(wsi);
718 
719 	//if (wsi->told_event_loop_closed) // cgi std close case (dummy-callback)
720 	//	return;
721 
722 	/* checking return redundant since we anyway close */
723 	__remove_wsi_socket_from_fds(wsi);
724 
725 	lwsi_set_state(wsi, LRS_DEAD_SOCKET);
726 	lws_buflist_destroy_all_segments(&wsi->buflist);
727 	lws_dll2_remove(&wsi->dll_buflist);
728 
729 	if (lws_rops_fidx(wsi->role_ops, LWS_ROPS_close_role))
730 		lws_rops_func_fidx(wsi->role_ops, LWS_ROPS_close_role).
731 							close_role(pt, wsi);
732 
733 	/* tell the user it's all over for this guy */
734 
735 	ccb = 0;
736 	if ((lwsi_state_est_PRE_CLOSE(wsi) ||
737 	    /* raw skt adopted but didn't complete tls hs should CLOSE */
738 	    (wsi->role_ops == &role_ops_raw_skt && !lwsi_role_client(wsi)) ||
739 	     lwsi_state_PRE_CLOSE(wsi) == LRS_WAITING_SERVER_REPLY) &&
740 	    !wsi->told_user_closed &&
741 	    wsi->role_ops->close_cb[lwsi_role_server(wsi)]) {
742 		if (!wsi->upgraded_to_http2 || !lwsi_role_client(wsi))
743 			ccb = 1;
744 			/*
745 			 * The network wsi for a client h2 connection shouldn't
746 			 * call back for its role: the child stream connections
747 			 * own the role.  Otherwise h2 will call back closed
748 			 * one too many times as the children do it and then
749 			 * the closing network stream.
750 			 */
751 	}
752 
753 	if (!wsi->told_user_closed &&
754 	    !lws_dll2_is_detached(&wsi->vh_awaiting_socket))
755 		/*
756 		 * He's a guy who go started with dns, but failed or is
757 		 * caught with a shutdown before he got the result.  We have
758 		 * to issclient_mux_substream_wasue him a close cb
759 		 */
760 		ccb = 1;
761 
762 	lwsl_wsi_info(wsi, "cce=%d", ccb);
763 
764 	pro = wsi->a.protocol;
765 
766 	if (wsi->already_did_cce)
767 		/*
768 		 * If we handled this by CLIENT_CONNECTION_ERROR, it's
769 		 * mutually exclusive with CLOSE
770 		 */
771 		ccb = 0;
772 
773 #if defined(LWS_WITH_CLIENT)
774 	if (!wsi->close_is_redirect && !ccb &&
775 	    (lwsi_state_PRE_CLOSE(wsi) & LWSIFS_NOT_EST) &&
776 			lwsi_role_client(wsi)) {
777 		lws_inform_client_conn_fail(wsi, "Closed before conn", 18);
778 	}
779 #endif
780 	if (ccb
781 #if defined(LWS_WITH_CLIENT)
782 			&& !wsi->close_is_redirect
783 #endif
784 	) {
785 
786 		if (!wsi->a.protocol && wsi->a.vhost && wsi->a.vhost->protocols)
787 			pro = &wsi->a.vhost->protocols[0];
788 
789 		if (pro)
790 			pro->callback(wsi,
791 				wsi->role_ops->close_cb[lwsi_role_server(wsi)],
792 				wsi->user_space, NULL, 0);
793 		wsi->told_user_closed = 1;
794 	}
795 
796 #if defined(LWS_ROLE_RAW_FILE)
797 async_close:
798 #endif
799 
800 #if defined(LWS_WITH_SECURE_STREAMS)
801 	if (wsi->for_ss) {
802 		lwsl_wsi_debug(wsi, "for_ss");
803 		/*
804 		 * We were adopted for a particular ss, but, eg, we may not
805 		 * have succeeded with the connection... we are closing which is
806 		 * good, but we have to invalidate any pointer the related ss
807 		 * handle may be holding on us
808 		 */
809 #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
810 
811 		if (wsi->client_proxy_onward) {
812 			/*
813 			 * We are an onward proxied wsi at the proxy,
814 			 * opaque is proxing "conn", we must remove its pointer
815 			 * to us since we are destroying
816 			 */
817 			lws_proxy_clean_conn_ss(wsi);
818 		} else
819 
820 			if (wsi->client_bound_sspc) {
821 				lws_sspc_handle_t *h = (lws_sspc_handle_t *)wsi->a.opaque_user_data;
822 
823 				if (h) { // && (h->info.flags & LWSSSINFLAGS_ACCEPTED)) {
824 
825 #if defined(LWS_WITH_SYS_METRICS)
826 					/*
827 					 * If any hanging caliper measurement, dump it, and free any tags
828 					 */
829 					lws_metrics_caliper_report_hist(h->cal_txn, (struct lws *)NULL);
830 #endif
831 
832 					h->cwsi = NULL;
833 					//wsi->a.opaque_user_data = NULL;
834 				}
835 			} else
836 #endif
837 		{
838 			lws_ss_handle_t *h = (lws_ss_handle_t *)wsi->a.opaque_user_data;
839 
840 			if (h) { // && (h->info.flags & LWSSSINFLAGS_ACCEPTED)) {
841 
842 				/*
843 				 * ss level: only reports if dangling caliper
844 				 * not already reported
845 				 */
846 				lws_metrics_caliper_report_hist(h->cal_txn, wsi);
847 
848 				h->wsi = NULL;
849 				wsi->a.opaque_user_data = NULL;
850 
851 				if (h->ss_dangling_connected &&
852 				    lws_ss_event_helper(h, LWSSSCS_DISCONNECTED) ==
853 						    LWSSSSRET_DESTROY_ME) {
854 
855 					lws_ss_destroy(&h);
856 				}
857 			}
858 		}
859 	}
860 #endif
861 
862 
863 	lws_remove_child_from_any_parent(wsi);
864 	wsi->socket_is_permanently_unusable = 1;
865 
866 	if (wsi->a.context->event_loop_ops->wsi_logical_close)
867 		if (wsi->a.context->event_loop_ops->wsi_logical_close(wsi))
868 			return;
869 
870 	__lws_close_free_wsi_final(wsi);
871 }
872 
873 
874 /* cx + vh lock */
875 
876 void
__lws_close_free_wsi_final(struct lws * wsi)877 __lws_close_free_wsi_final(struct lws *wsi)
878 {
879 	int n;
880 
881 	if (!wsi->shadow &&
882 	    lws_socket_is_valid(wsi->desc.sockfd) && !lws_ssl_close(wsi)) {
883 		lwsl_wsi_debug(wsi, "fd %d", wsi->desc.sockfd);
884 		n = compatible_close(wsi->desc.sockfd);
885 		if (n)
886 			lwsl_wsi_debug(wsi, "closing: close ret %d", LWS_ERRNO);
887 
888 		__remove_wsi_socket_from_fds(wsi);
889 		if (lws_socket_is_valid(wsi->desc.sockfd))
890 			delete_from_fd(wsi->a.context, wsi->desc.sockfd);
891 
892 #if !defined(LWS_PLAT_FREERTOS) && !defined(WIN32) && !defined(LWS_PLAT_OPTEE)
893 		delete_from_fdwsi(wsi->a.context, wsi);
894 #endif
895 
896 		sanity_assert_no_sockfd_traces(wsi->a.context, wsi->desc.sockfd);
897 	}
898 
899 	/* ... if we're closing the cancel pipe, account for it */
900 
901 	{
902 		struct lws_context_per_thread *pt =
903 				&wsi->a.context->pt[(int)wsi->tsi];
904 
905 		if (pt->pipe_wsi == wsi)
906 			pt->pipe_wsi = NULL;
907 		if (pt->dummy_pipe_fds[0] == wsi->desc.sockfd)
908 			pt->dummy_pipe_fds[0] = LWS_SOCK_INVALID;
909 	}
910 
911 	wsi->desc.sockfd = LWS_SOCK_INVALID;
912 
913 #if defined(LWS_WITH_CLIENT)
914 	lws_free_set_NULL(wsi->cli_hostname_copy);
915 	if (wsi->close_is_redirect) {
916 
917 		wsi->close_is_redirect = 0;
918 
919 		lwsl_wsi_info(wsi, "picking up redirection");
920 
921 		lws_role_transition(wsi, LWSIFR_CLIENT, LRS_UNCONNECTED,
922 				    &role_ops_h1);
923 
924 #if defined(LWS_WITH_HTTP2)
925 		if (wsi->client_mux_substream_was)
926 			wsi->h2.END_STREAM = wsi->h2.END_HEADERS = 0;
927 #endif
928 #if defined(LWS_ROLE_H2) || defined(LWS_ROLE_MQTT)
929 		if (wsi->mux.parent_wsi) {
930 			lws_wsi_mux_sibling_disconnect(wsi);
931 			wsi->mux.parent_wsi = NULL;
932 		}
933 #endif
934 
935 #if defined(LWS_WITH_TLS)
936 		memset(&wsi->tls, 0, sizeof(wsi->tls));
937 #endif
938 
939 	//	wsi->a.protocol = NULL;
940 		if (wsi->a.protocol)
941 			lws_bind_protocol(wsi, wsi->a.protocol, "client_reset");
942 		wsi->pending_timeout = NO_PENDING_TIMEOUT;
943 		wsi->hdr_parsing_completed = 0;
944 
945 #if defined(LWS_WITH_TLS)
946 		if (wsi->stash->cis[CIS_ALPN])
947 			lws_strncpy(wsi->alpn, wsi->stash->cis[CIS_ALPN],
948 				    sizeof(wsi->alpn));
949 #endif
950 
951 		if (lws_header_table_attach(wsi, 0)) {
952 			lwsl_wsi_err(wsi, "failed to get ah");
953 			return;
954 		}
955 //		}
956 		//_lws_header_table_reset(wsi->http.ah);
957 
958 #if defined(LWS_WITH_TLS)
959 		wsi->tls.use_ssl = (unsigned int)wsi->flags;
960 #endif
961 
962 #if defined(LWS_WITH_TLS_JIT_TRUST)
963 		if (wsi->stash && wsi->stash->cis[CIS_ADDRESS]) {
964 			struct lws_vhost *vh = NULL;
965 			lws_tls_jit_trust_vhost_bind(wsi->a.context,
966 						     wsi->stash->cis[CIS_ADDRESS],
967 						     &vh);
968 			if (vh) {
969 				if (!vh->count_bound_wsi && vh->grace_after_unref) {
970 					lwsl_wsi_info(wsi, "%s in use\n",
971 								vh->lc.gutag);
972 					lws_sul_cancel(&vh->sul_unref);
973 				}
974 				vh->count_bound_wsi++;
975 				wsi->a.vhost = vh;
976 			}
977 		}
978 #endif
979 
980 		return;
981 	}
982 #endif
983 
984 	/* outermost destroy notification for wsi (user_space still intact) */
985 	if (wsi->a.vhost)
986 		wsi->a.vhost->protocols[0].callback(wsi, LWS_CALLBACK_WSI_DESTROY,
987 						  wsi->user_space, NULL, 0);
988 
989 #ifdef LWS_WITH_CGI
990 	if (wsi->http.cgi) {
991 		lws_spawn_piped_destroy(&wsi->http.cgi->lsp);
992 		lws_sul_cancel(&wsi->http.cgi->sul_grace);
993 		lws_free_set_NULL(wsi->http.cgi);
994 	}
995 #endif
996 
997 #if defined(LWS_WITH_SYS_FAULT_INJECTION)
998 	lws_fi_destroy(&wsi->fic);
999 #endif
1000 
1001 	__lws_wsi_remove_from_sul(wsi);
1002 	sanity_assert_no_wsi_traces(wsi->a.context, wsi);
1003 	__lws_free_wsi(wsi);
1004 }
1005 
1006 
1007 void
lws_close_free_wsi(struct lws * wsi,enum lws_close_status reason,const char * caller)1008 lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, const char *caller)
1009 {
1010 	struct lws_context *cx = wsi->a.context;
1011 	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
1012 
1013 	lws_context_lock(cx, __func__);
1014 
1015 	lws_pt_lock(pt, __func__);
1016 	/* may destroy vhost, cannot hold vhost lock outside it */
1017 	__lws_close_free_wsi(wsi, reason, caller);
1018 	lws_pt_unlock(pt);
1019 
1020 	lws_context_unlock(cx);
1021 }
1022 
1023 
1024