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
27const char *
28lws_wsi_tag(struct lws *wsi)
29{
30	if (!wsi)
31		return "[null wsi]";
32	return lws_lc_tag(&wsi->lc);
33}
34
35#if defined (_DEBUG)
36void lwsi_set_role(struct lws *wsi, lws_wsi_state_t role)
37{
38	wsi->wsistate = (wsi->wsistate & (~LWSI_ROLE_MASK)) | role;
39
40	lwsl_wsi_debug(wsi, "state 0x%lx", (unsigned long)wsi->wsistate);
41}
42
43void lwsi_set_state(struct lws *wsi, lws_wsi_state_t lrs)
44{
45	lws_wsi_state_t old = wsi->wsistate;
46
47	wsi->wsistate = (old & (unsigned int)(~LRS_MASK)) | lrs;
48
49	lwsl_wsi_debug(wsi, "lwsi_set_state 0x%lx -> 0x%lx",
50			(unsigned long)old, (unsigned long)wsi->wsistate);
51}
52#endif
53
54
55void
56lws_log_prepend_wsi(struct lws_log_cx *cx, void *obj, char **p, char *e)
57{
58	struct lws *wsi = (struct lws *)obj;
59
60	*p += lws_snprintf(*p, lws_ptr_diff_size_t(e, (*p)), "%s: ",
61							lws_wsi_tag(wsi));
62}
63
64void
65lws_vhost_bind_wsi(struct lws_vhost *vh, struct lws *wsi)
66{
67	if (wsi->a.vhost == vh)
68		return;
69
70	lws_context_lock(vh->context, __func__); /* ---------- context { */
71	wsi->a.vhost = vh;
72
73#if defined(LWS_WITH_TLS_JIT_TRUST)
74	if (!vh->count_bound_wsi && vh->grace_after_unref) {
75		lwsl_wsi_info(wsi, "in use");
76		lws_sul_cancel(&vh->sul_unref);
77	}
78#endif
79
80	vh->count_bound_wsi++;
81	lws_context_unlock(vh->context); /* } context ---------- */
82
83	lwsl_wsi_debug(wsi, "vh %s: wsi %s/%s, count_bound_wsi %d\n",
84		   vh->name, wsi->role_ops ? wsi->role_ops->name : "none",
85		   wsi->a.protocol ? wsi->a.protocol->name : "none",
86		   vh->count_bound_wsi);
87	assert(wsi->a.vhost->count_bound_wsi > 0);
88}
89
90
91/* req cx lock... acquires vh lock */
92void
93__lws_vhost_unbind_wsi(struct lws *wsi)
94{
95        struct lws_vhost *vh = wsi->a.vhost;
96
97        if (!vh)
98                return;
99
100	lws_context_assert_lock_held(wsi->a.context);
101
102	lws_vhost_lock(vh);
103
104	assert(vh->count_bound_wsi > 0);
105	vh->count_bound_wsi--;
106
107#if defined(LWS_WITH_TLS_JIT_TRUST)
108	if (!vh->count_bound_wsi && vh->grace_after_unref)
109		lws_tls_jit_trust_vh_start_grace(vh);
110#endif
111
112	lwsl_wsi_debug(wsi, "vh %s: count_bound_wsi %d",
113		   vh->name, vh->count_bound_wsi);
114
115	lws_vhost_unlock(vh);
116
117	if (!vh->count_bound_wsi && vh->being_destroyed)
118		/*
119		 * We have closed all wsi that were bound to this vhost
120		 * by any pt: nothing can be servicing any wsi belonging
121		 * to it any more.
122		 *
123		 * Finalize the vh destruction... must drop vh lock
124		 */
125		__lws_vhost_destroy2(vh);
126
127	wsi->a.vhost = NULL;
128}
129
130struct lws *
131lws_get_network_wsi(struct lws *wsi)
132{
133	if (!wsi)
134		return NULL;
135
136#if defined(LWS_WITH_HTTP2) || defined(LWS_ROLE_MQTT)
137	if (!wsi->mux_substream
138#if defined(LWS_WITH_CLIENT)
139			&& !wsi->client_mux_substream
140#endif
141	)
142		return wsi;
143
144	while (wsi->mux.parent_wsi)
145		wsi = wsi->mux.parent_wsi;
146#endif
147
148	return wsi;
149}
150
151
152const struct lws_protocols *
153lws_vhost_name_to_protocol(struct lws_vhost *vh, const char *name)
154{
155	int n;
156
157	for (n = 0; n < vh->count_protocols; n++)
158		if (vh->protocols[n].name && !strcmp(name, vh->protocols[n].name))
159			return &vh->protocols[n];
160
161	return NULL;
162}
163
164int
165lws_callback_all_protocol(struct lws_context *context,
166			  const struct lws_protocols *protocol, int reason)
167{
168	struct lws_context_per_thread *pt = &context->pt[0];
169	unsigned int n, m = context->count_threads;
170	struct lws *wsi;
171
172	while (m--) {
173		for (n = 0; n < pt->fds_count; n++) {
174			wsi = wsi_from_fd(context, pt->fds[n].fd);
175			if (!wsi)
176				continue;
177			if (wsi->a.protocol == protocol)
178				protocol->callback(wsi,
179					(enum lws_callback_reasons)reason,
180					wsi->user_space, NULL, 0);
181		}
182		pt++;
183	}
184
185	return 0;
186}
187
188void *
189lws_evlib_wsi_to_evlib_pt(struct lws *wsi)
190{
191	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
192
193	return pt->evlib_pt;
194}
195
196void *
197lws_evlib_tsi_to_evlib_pt(struct lws_context *cx, int tsi)
198{
199	struct lws_context_per_thread *pt = &cx->pt[tsi];
200
201	return pt->evlib_pt;
202}
203
204int
205lws_callback_all_protocol_vhost_args(struct lws_vhost *vh,
206			  const struct lws_protocols *protocol, int reason,
207			  void *argp, size_t len)
208{
209	struct lws_context *context = vh->context;
210	struct lws_context_per_thread *pt = &context->pt[0];
211	unsigned int n, m = context->count_threads;
212	struct lws *wsi;
213
214	while (m--) {
215		for (n = 0; n < pt->fds_count; n++) {
216			wsi = wsi_from_fd(context, pt->fds[n].fd);
217			if (!wsi)
218				continue;
219			if (wsi->a.vhost == vh && (wsi->a.protocol == protocol ||
220						 !protocol))
221				wsi->a.protocol->callback(wsi, (enum lws_callback_reasons)reason,
222						wsi->user_space, argp, len);
223		}
224		pt++;
225	}
226
227	return 0;
228}
229
230int
231lws_callback_all_protocol_vhost(struct lws_vhost *vh,
232			  const struct lws_protocols *protocol, int reason)
233{
234	return lws_callback_all_protocol_vhost_args(vh, protocol, reason, NULL, 0);
235}
236
237int
238lws_callback_vhost_protocols(struct lws *wsi, int reason, void *in, size_t len)
239{
240	int n;
241
242	for (n = 0; n < wsi->a.vhost->count_protocols; n++)
243		if (wsi->a.vhost->protocols[n].callback(wsi, (enum lws_callback_reasons)reason, NULL, in, len))
244			return 1;
245
246	return 0;
247}
248
249#if defined(LWS_WITH_SYS_FAULT_INJECTION)
250/*
251 * We want to inject a fault that makes it feel like the peer hung up on us,
252 * or we were otherwise cut off.
253 */
254void
255lws_wsi_fault_timedclose_cb(lws_sorted_usec_list_t *s)
256{
257	struct lws *wsi = lws_container_of(s, struct lws, sul_fault_timedclose);
258
259	lwsl_wsi_warn(wsi, "force-closing");
260	lws_wsi_close(wsi, LWS_TO_KILL_ASYNC);
261}
262#endif
263
264#if defined(LWS_WITH_SYS_FAULT_INJECTION)
265void
266lws_wsi_fault_timedclose(struct lws *wsi)
267{
268	uint64_t u;
269
270	if (!lws_fi(&wsi->fic, "timedclose"))
271		return;
272
273	if (lws_fi_range(&wsi->fic, "timedclose_ms", &u))
274		return;
275
276	lwsl_wsi_warn(wsi, "injecting close in %ums", (unsigned int)u);
277	lws_sul_schedule(wsi->a.context, wsi->tsi, &wsi->sul_fault_timedclose,
278			 lws_wsi_fault_timedclose_cb,
279			 (lws_usec_t)(u * 1000ull));
280}
281#endif
282
283
284/*
285 * We need the context lock
286 */
287
288struct lws *
289__lws_wsi_create_with_role(struct lws_context *context, int tsi,
290			   const struct lws_role_ops *ops,
291			   lws_log_cx_t *log_cx_template)
292{
293	size_t s = sizeof(struct lws);
294	struct lws *wsi;
295
296	assert(tsi >= 0 && tsi < LWS_MAX_SMP);
297
298	lws_context_assert_lock_held(context);
299
300#if defined(LWS_WITH_EVENT_LIBS)
301	s += context->event_loop_ops->evlib_size_wsi;
302#endif
303
304	wsi = lws_zalloc(s, __func__);
305
306	if (!wsi) {
307		lwsl_cx_err(context, "OOM");
308		return NULL;
309	}
310
311	if (log_cx_template)
312		wsi->lc.log_cx = log_cx_template;
313	else
314		wsi->lc.log_cx = context->log_cx;
315
316#if defined(LWS_WITH_EVENT_LIBS)
317	wsi->evlib_wsi = (uint8_t *)wsi + sizeof(*wsi);
318#endif
319	wsi->a.context = context;
320	lws_role_transition(wsi, 0, LRS_UNCONNECTED, ops);
321	wsi->pending_timeout = NO_PENDING_TIMEOUT;
322	wsi->a.protocol = NULL;
323	wsi->tsi = (char)tsi;
324	wsi->a.vhost = NULL;
325	wsi->desc.sockfd = LWS_SOCK_INVALID;
326	wsi->position_in_fds_table = LWS_NO_FDS_POS;
327
328#if defined(LWS_WITH_SYS_FAULT_INJECTION)
329	lws_xos_init(&wsi->fic.xos, lws_xos(&context->fic.xos));
330#endif
331
332	lws_fi_inherit_copy(&wsi->fic, &context->fic, "wsi", NULL);
333
334	if (lws_fi(&wsi->fic, "createfail")) {
335		lws_fi_destroy(&wsi->fic);
336		lws_free(wsi);
337		return NULL;
338	}
339
340	return wsi;
341}
342
343int
344lws_wsi_inject_to_loop(struct lws_context_per_thread *pt, struct lws *wsi)
345{
346	int ret = 1;
347
348	lws_pt_lock(pt, __func__); /* -------------- pt { */
349
350	if (pt->context->event_loop_ops->sock_accept)
351		if (pt->context->event_loop_ops->sock_accept(wsi))
352			goto bail;
353
354	if (__insert_wsi_socket_into_fds(pt->context, wsi))
355		goto bail;
356
357	ret = 0;
358
359bail:
360	lws_pt_unlock(pt);
361
362	return ret;
363}
364
365/*
366 * Take a copy of wsi->desc.sockfd before calling this, then close it
367 * afterwards
368 */
369
370int
371lws_wsi_extract_from_loop(struct lws *wsi)
372{
373	if (lws_socket_is_valid(wsi->desc.sockfd))
374		__remove_wsi_socket_from_fds(wsi);
375
376	if (!wsi->a.context->event_loop_ops->destroy_wsi &&
377	    wsi->a.context->event_loop_ops->wsi_logical_close) {
378		wsi->a.context->event_loop_ops->wsi_logical_close(wsi);
379		return 1; /* close / destroy continues async */
380	}
381
382	if (wsi->a.context->event_loop_ops->destroy_wsi)
383		wsi->a.context->event_loop_ops->destroy_wsi(wsi);
384
385	return 0; /* he is destroyed */
386}
387
388int
389lws_callback_vhost_protocols_vhost(struct lws_vhost *vh, int reason, void *in,
390				   size_t len)
391{
392	int n;
393	struct lws *wsi = lws_zalloc(sizeof(*wsi), "fake wsi");
394
395	if (!wsi)
396		return 1;
397
398	wsi->a.context = vh->context;
399	lws_vhost_bind_wsi(vh, wsi);
400
401	for (n = 0; n < wsi->a.vhost->count_protocols; n++) {
402		wsi->a.protocol = &vh->protocols[n];
403		if (wsi->a.protocol->callback(wsi, (enum lws_callback_reasons)reason, NULL, in, len)) {
404			lws_free(wsi);
405			return 1;
406		}
407	}
408
409	lws_free(wsi);
410
411	return 0;
412}
413
414
415int
416lws_rx_flow_control(struct lws *wsi, int _enable)
417{
418	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
419	int en = _enable;
420
421	// h2 ignores rx flow control atm
422	if (lwsi_role_h2(wsi) || wsi->mux_substream ||
423	    lwsi_role_h2_ENCAPSULATION(wsi))
424		return 0; // !!!
425
426	lwsl_wsi_info(wsi, "0x%x", _enable);
427
428	if (!(_enable & LWS_RXFLOW_REASON_APPLIES)) {
429		/*
430		 * convert user bool style to bitmap style... in user simple
431		 * bool style _enable = 0 = flow control it, = 1 = allow rx
432		 */
433		en = LWS_RXFLOW_REASON_APPLIES | LWS_RXFLOW_REASON_USER_BOOL;
434		if (_enable & 1)
435			en |= LWS_RXFLOW_REASON_APPLIES_ENABLE_BIT;
436	}
437
438	lws_pt_lock(pt, __func__);
439
440	/* any bit set in rxflow_bitmap DISABLEs rxflow control */
441	if (en & LWS_RXFLOW_REASON_APPLIES_ENABLE_BIT)
442		wsi->rxflow_bitmap = (uint8_t)(wsi->rxflow_bitmap & ~(en & 0xff));
443	else
444		wsi->rxflow_bitmap = (uint8_t)(wsi->rxflow_bitmap | (en & 0xff));
445
446	if ((LWS_RXFLOW_PENDING_CHANGE | (!wsi->rxflow_bitmap)) ==
447	    wsi->rxflow_change_to)
448		goto skip;
449
450	wsi->rxflow_change_to = LWS_RXFLOW_PENDING_CHANGE |
451				(!wsi->rxflow_bitmap);
452
453	lwsl_wsi_info(wsi, "bitmap 0x%x: en 0x%x, ch 0x%x",
454			   wsi->rxflow_bitmap, en, wsi->rxflow_change_to);
455
456	if (_enable & LWS_RXFLOW_REASON_FLAG_PROCESS_NOW ||
457	    !wsi->rxflow_will_be_applied) {
458		en = __lws_rx_flow_control(wsi);
459		lws_pt_unlock(pt);
460
461		return en;
462	}
463
464skip:
465	lws_pt_unlock(pt);
466
467	return 0;
468}
469
470void
471lws_rx_flow_allow_all_protocol(const struct lws_context *context,
472			       const struct lws_protocols *protocol)
473{
474	const struct lws_context_per_thread *pt = &context->pt[0];
475	struct lws *wsi;
476	unsigned int n, m = context->count_threads;
477
478	while (m--) {
479		for (n = 0; n < pt->fds_count; n++) {
480			wsi = wsi_from_fd(context, pt->fds[n].fd);
481			if (!wsi)
482				continue;
483			if (wsi->a.protocol == protocol)
484				lws_rx_flow_control(wsi, LWS_RXFLOW_ALLOW);
485		}
486		pt++;
487	}
488}
489
490int user_callback_handle_rxflow(lws_callback_function callback_function,
491				struct lws *wsi,
492				enum lws_callback_reasons reason, void *user,
493				void *in, size_t len)
494{
495	int n;
496
497	wsi->rxflow_will_be_applied = 1;
498	n = callback_function(wsi, reason, user, in, len);
499	wsi->rxflow_will_be_applied = 0;
500	if (!n)
501		n = __lws_rx_flow_control(wsi);
502
503	return n;
504}
505
506int
507__lws_rx_flow_control(struct lws *wsi)
508{
509	struct lws *wsic = wsi->child_list;
510
511	// h2 ignores rx flow control atm
512	if (lwsi_role_h2(wsi) || wsi->mux_substream ||
513	    lwsi_role_h2_ENCAPSULATION(wsi))
514		return 0; // !!!
515
516	/* if he has children, do those if they were changed */
517	while (wsic) {
518		if (wsic->rxflow_change_to & LWS_RXFLOW_PENDING_CHANGE)
519			__lws_rx_flow_control(wsic);
520
521		wsic = wsic->sibling_list;
522	}
523
524	/* there is no pending change */
525	if (!(wsi->rxflow_change_to & LWS_RXFLOW_PENDING_CHANGE))
526		return 0;
527
528	/* stuff is still buffered, not ready to really accept new input */
529	if (lws_buflist_next_segment_len(&wsi->buflist, NULL)) {
530		/* get ourselves called back to deal with stashed buffer */
531		lws_callback_on_writable(wsi);
532		// return 0;
533	}
534
535	/* now the pending is cleared, we can change rxflow state */
536
537	wsi->rxflow_change_to &= (~LWS_RXFLOW_PENDING_CHANGE) & 3;
538
539	lwsl_wsi_info(wsi, "rxflow: change_to %d",
540		      wsi->rxflow_change_to & LWS_RXFLOW_ALLOW);
541
542	/* adjust the pollfd for this wsi */
543
544	if (wsi->rxflow_change_to & LWS_RXFLOW_ALLOW) {
545		lwsl_wsi_info(wsi, "reenable POLLIN");
546		// lws_buflist_describe(&wsi->buflist, NULL, __func__);
547		if (__lws_change_pollfd(wsi, 0, LWS_POLLIN)) {
548			lwsl_wsi_info(wsi, "fail");
549			return -1;
550		}
551	} else
552		if (__lws_change_pollfd(wsi, LWS_POLLIN, 0))
553			return -1;
554
555	return 0;
556}
557
558
559const struct lws_protocols *
560lws_get_protocol(struct lws *wsi)
561{
562	return wsi->a.protocol;
563}
564
565
566int
567lws_ensure_user_space(struct lws *wsi)
568{
569	if (!wsi->a.protocol)
570		return 0;
571
572	/* allocate the per-connection user memory (if any) */
573
574	if (wsi->a.protocol->per_session_data_size && !wsi->user_space) {
575		wsi->user_space = lws_zalloc(
576			    wsi->a.protocol->per_session_data_size, "user space");
577		if (wsi->user_space == NULL) {
578			lwsl_wsi_err(wsi, "OOM");
579			return 1;
580		}
581	} else
582		lwsl_wsi_debug(wsi, "protocol pss %lu, user_space=%p",
583				    (long)wsi->a.protocol->per_session_data_size,
584				    wsi->user_space);
585	return 0;
586}
587
588void *
589lws_adjust_protocol_psds(struct lws *wsi, size_t new_size)
590{
591	((struct lws_protocols *)lws_get_protocol(wsi))->per_session_data_size =
592		new_size;
593
594	if (lws_ensure_user_space(wsi))
595			return NULL;
596
597	return wsi->user_space;
598}
599
600int
601lws_get_tsi(struct lws *wsi)
602{
603        return (int)wsi->tsi;
604}
605
606int
607lws_is_ssl(struct lws *wsi)
608{
609#if defined(LWS_WITH_TLS)
610	return wsi->tls.use_ssl & LCCSCF_USE_SSL;
611#else
612	(void)wsi;
613	return 0;
614#endif
615}
616
617#if defined(LWS_WITH_TLS) && !defined(LWS_WITH_MBEDTLS)
618lws_tls_conn*
619lws_get_ssl(struct lws *wsi)
620{
621	return wsi->tls.ssl;
622}
623#endif
624
625int
626lws_has_buffered_out(struct lws *wsi)
627{
628	if (wsi->buflist_out)
629		return 1;
630
631#if defined(LWS_ROLE_H2)
632	{
633		struct lws *nwsi = lws_get_network_wsi(wsi);
634
635		if (nwsi->buflist_out)
636			return 1;
637	}
638#endif
639
640	return 0;
641}
642
643int
644lws_partial_buffered(struct lws *wsi)
645{
646	return lws_has_buffered_out(wsi);
647}
648
649lws_fileofs_t
650lws_get_peer_write_allowance(struct lws *wsi)
651{
652	if (!lws_rops_fidx(wsi->role_ops, LWS_ROPS_tx_credit))
653		return -1;
654
655	return lws_rops_func_fidx(wsi->role_ops, LWS_ROPS_tx_credit).
656				   tx_credit(wsi, LWSTXCR_US_TO_PEER, 0);
657}
658
659void
660lws_role_transition(struct lws *wsi, enum lwsi_role role, enum lwsi_state state,
661		    const struct lws_role_ops *ops)
662{
663#if (_LWS_ENABLED_LOGS & LLL_DEBUG)
664	const char *name = "(unset)";
665#endif
666	wsi->wsistate = (unsigned int)role | (unsigned int)state;
667	if (ops)
668		wsi->role_ops = ops;
669#if (_LWS_ENABLED_LOGS & LLL_DEBUG)
670	if (wsi->role_ops)
671		name = wsi->role_ops->name;
672	lwsl_wsi_debug(wsi, "wsistate 0x%lx, ops %s",
673			    (unsigned long)wsi->wsistate, name);
674#endif
675}
676
677int
678lws_parse_uri(char *p, const char **prot, const char **ads, int *port,
679	      const char **path)
680{
681	const char *end;
682	char unix_skt = 0;
683
684	/* cut up the location into address, port and path */
685	*prot = p;
686	while (*p && (*p != ':' || p[1] != '/' || p[2] != '/'))
687		p++;
688	if (!*p) {
689		end = p;
690		p = (char *)*prot;
691		*prot = end;
692	} else {
693		*p = '\0';
694		p += 3;
695	}
696	if (*p == '+') /* unix skt */
697		unix_skt = 1;
698
699	*ads = p;
700	if (!strcmp(*prot, "http") || !strcmp(*prot, "ws"))
701		*port = 80;
702	else if (!strcmp(*prot, "https") || !strcmp(*prot, "wss"))
703		*port = 443;
704
705	if (*p == '[') {
706		++(*ads);
707		while (*p && *p != ']')
708			p++;
709		if (*p)
710			*p++ = '\0';
711	} else
712		while (*p && *p != ':' && (unix_skt || *p != '/'))
713			p++;
714
715	if (*p == ':') {
716		*p++ = '\0';
717		*port = atoi(p);
718		while (*p && *p != '/')
719			p++;
720	}
721	*path = "/";
722	if (*p) {
723		*p++ = '\0';
724		if (*p)
725			*path = p;
726	}
727
728	return 0;
729}
730
731/* ... */
732
733int
734lws_get_urlarg_by_name_safe(struct lws *wsi, const char *name, char *buf, int len)
735{
736	int n = 0, fraglen, sl = (int)strlen(name);
737
738	do {
739		fraglen = lws_hdr_copy_fragment(wsi, buf, len,
740						WSI_TOKEN_HTTP_URI_ARGS, n);
741
742		if (fraglen < 0)
743			break;
744
745		if (fraglen + 1 < len &&
746		    fraglen >= sl &&
747		    !strncmp(buf, name, (size_t)sl)) {
748			/*
749			 * If he left off the trailing =, trim it from the
750			 * result
751			 */
752
753			if (name[sl - 1] != '=' &&
754			    sl < fraglen &&
755			    buf[sl] == '=')
756				sl++;
757
758			memmove(buf, buf + sl, (size_t)(fraglen - sl));
759			buf[fraglen - sl] = '\0';
760
761			return fraglen - sl;
762		}
763
764		n++;
765	} while (1);
766
767	return -1;
768}
769
770const char *
771lws_get_urlarg_by_name(struct lws *wsi, const char *name, char *buf, int len)
772{
773	int n = lws_get_urlarg_by_name_safe(wsi, name, buf, len);
774
775	return n < 0 ? NULL : buf;
776}
777
778
779#if defined(LWS_WITHOUT_EXTENSIONS)
780
781/* we need to provide dummy callbacks for internal exts
782 * so user code runs when faced with a lib compiled with
783 * extensions disabled.
784 */
785
786int
787lws_extension_callback_pm_deflate(struct lws_context *context,
788                                  const struct lws_extension *ext,
789                                  struct lws *wsi,
790                                  enum lws_extension_callback_reasons reason,
791                                  void *user, void *in, size_t len)
792{
793	(void)context;
794	(void)ext;
795	(void)wsi;
796	(void)reason;
797	(void)user;
798	(void)in;
799	(void)len;
800
801	return 0;
802}
803
804int
805lws_set_extension_option(struct lws *wsi, const char *ext_name,
806			 const char *opt_name, const char *opt_val)
807{
808	return -1;
809}
810#endif
811
812int
813lws_is_cgi(struct lws *wsi) {
814#ifdef LWS_WITH_CGI
815	return !!wsi->http.cgi;
816#else
817	return 0;
818#endif
819}
820
821const struct lws_protocol_vhost_options *
822lws_pvo_search(const struct lws_protocol_vhost_options *pvo, const char *name)
823{
824	while (pvo) {
825		if (!strcmp(pvo->name, name))
826			break;
827
828		pvo = pvo->next;
829	}
830
831	return pvo;
832}
833
834int
835lws_pvo_get_str(void *in, const char *name, const char **result)
836{
837	const struct lws_protocol_vhost_options *pv =
838		lws_pvo_search((const struct lws_protocol_vhost_options *)in,
839				name);
840
841	if (!pv)
842		return 1;
843
844	*result = (const char *)pv->value;
845
846	return 0;
847}
848
849int
850lws_broadcast(struct lws_context_per_thread *pt, int reason, void *in, size_t len)
851{
852	struct lws_vhost *v = pt->context->vhost_list;
853	lws_fakewsi_def_plwsa(pt);
854	int n, ret = 0;
855
856	lws_fakewsi_prep_plwsa_ctx(pt->context);
857#if !defined(LWS_PLAT_FREERTOS) && LWS_MAX_SMP > 1
858	((struct lws *)plwsa)->tsi = (char)(int)(pt - &pt->context->pt[0]);
859#endif
860
861	while (v) {
862		const struct lws_protocols *p = v->protocols;
863
864		plwsa->vhost = v; /* not a real bound wsi */
865
866		for (n = 0; n < v->count_protocols; n++) {
867			plwsa->protocol = p;
868			if (p->callback &&
869			    p->callback((struct lws *)plwsa, (enum lws_callback_reasons)reason, NULL, in, len))
870				ret |= 1;
871			p++;
872		}
873
874		v = v->vhost_next;
875	}
876
877	return ret;
878}
879
880void *
881lws_wsi_user(struct lws *wsi)
882{
883	return wsi->user_space;
884}
885
886int
887lws_wsi_tsi(struct lws *wsi)
888{
889	return wsi->tsi;
890}
891
892
893void
894lws_set_wsi_user(struct lws *wsi, void *data)
895{
896	if (!wsi->user_space_externally_allocated && wsi->user_space)
897		lws_free(wsi->user_space);
898
899	wsi->user_space_externally_allocated = 1;
900	wsi->user_space = data;
901}
902
903struct lws *
904lws_get_parent(const struct lws *wsi)
905{
906	return wsi->parent;
907}
908
909struct lws *
910lws_get_child(const struct lws *wsi)
911{
912	return wsi->child_list;
913}
914
915void *
916lws_get_opaque_parent_data(const struct lws *wsi)
917{
918	return wsi->opaque_parent_data;
919}
920
921void
922lws_set_opaque_parent_data(struct lws *wsi, void *data)
923{
924	wsi->opaque_parent_data = data;
925}
926
927void *
928lws_get_opaque_user_data(const struct lws *wsi)
929{
930	return wsi->a.opaque_user_data;
931}
932
933void
934lws_set_opaque_user_data(struct lws *wsi, void *data)
935{
936	wsi->a.opaque_user_data = data;
937}
938
939int
940lws_get_child_pending_on_writable(const struct lws *wsi)
941{
942	return wsi->parent_pending_cb_on_writable;
943}
944
945void
946lws_clear_child_pending_on_writable(struct lws *wsi)
947{
948	wsi->parent_pending_cb_on_writable = 0;
949}
950
951
952
953const char *
954lws_get_vhost_name(struct lws_vhost *vhost)
955{
956	return vhost->name;
957}
958
959int
960lws_get_vhost_port(struct lws_vhost *vhost)
961{
962	return vhost->listen_port;
963}
964
965void *
966lws_get_vhost_user(struct lws_vhost *vhost)
967{
968	return vhost->user;
969}
970
971const char *
972lws_get_vhost_iface(struct lws_vhost *vhost)
973{
974	return vhost->iface;
975}
976
977lws_sockfd_type
978lws_get_socket_fd(struct lws *wsi)
979{
980	if (!wsi)
981		return -1;
982	return wsi->desc.sockfd;
983}
984
985
986struct lws_vhost *
987lws_vhost_get(struct lws *wsi)
988{
989	return wsi->a.vhost;
990}
991
992struct lws_vhost *
993lws_get_vhost(struct lws *wsi)
994{
995	return wsi->a.vhost;
996}
997
998const struct lws_protocols *
999lws_protocol_get(struct lws *wsi)
1000{
1001	return wsi->a.protocol;
1002}
1003
1004#if defined(LWS_WITH_UDP)
1005const struct lws_udp *
1006lws_get_udp(const struct lws *wsi)
1007{
1008	return wsi->udp;
1009}
1010#endif
1011
1012struct lws_context *
1013lws_get_context(const struct lws *wsi)
1014{
1015	return wsi->a.context;
1016}
1017
1018struct lws_log_cx *
1019lwsl_wsi_get_cx(struct lws *wsi)
1020{
1021	if (!wsi)
1022		return NULL;
1023
1024	return wsi->lc.log_cx;
1025}
1026
1027#if defined(LWS_WITH_CLIENT)
1028int
1029_lws_generic_transaction_completed_active_conn(struct lws **_wsi, char take_vh_lock)
1030{
1031	struct lws *wnew, *wsi = *_wsi;
1032
1033	/*
1034	 * Are we constitutionally capable of having a queue, ie, we are on
1035	 * the "active client connections" list?
1036	 *
1037	 * If not, that's it for us.
1038	 */
1039
1040	if (lws_dll2_is_detached(&wsi->dll_cli_active_conns))
1041		return 0; /* no new transaction */
1042
1043	/*
1044	 * With h1 queuing, the original "active client" moves his attributes
1045	 * like fd, ssl, queue and active client list entry to the next guy in
1046	 * the queue before closing... it's because the user code knows the
1047	 * individual wsi and the action must take place in the correct wsi
1048	 * context.  Note this means we don't truly pipeline headers.
1049	 *
1050	 * Trying to keep the original "active client" in place to do the work
1051	 * of the wsi breaks down when dealing with queued POSTs otherwise; it's
1052	 * also competing with the real mux child arrangements and complicating
1053	 * the code.
1054	 *
1055	 * For that reason, see if we have any queued child now...
1056	 */
1057
1058	if (!wsi->dll2_cli_txn_queue_owner.head) {
1059		/*
1060		 * Nothing pipelined... we should hang around a bit
1061		 * in case something turns up... otherwise we'll close
1062		 */
1063		lwsl_wsi_info(wsi, "nothing pipelined waiting");
1064		lwsi_set_state(wsi, LRS_IDLING);
1065
1066		lws_set_timeout(wsi, PENDING_TIMEOUT_CLIENT_CONN_IDLE,
1067				wsi->keep_warm_secs);
1068
1069		return 0; /* no new transaction right now */
1070	}
1071
1072	/*
1073	 * We have a queued child wsi we should bequeath our assets to, before
1074	 * closing ourself
1075	 */
1076
1077	if (take_vh_lock)
1078		lws_vhost_lock(wsi->a.vhost);
1079
1080	wnew = lws_container_of(wsi->dll2_cli_txn_queue_owner.head, struct lws,
1081				dll2_cli_txn_queue);
1082
1083	assert(wsi != wnew);
1084
1085	lws_dll2_remove(&wnew->dll2_cli_txn_queue);
1086
1087	assert(lws_socket_is_valid(wsi->desc.sockfd));
1088
1089	__lws_change_pollfd(wsi, LWS_POLLOUT | LWS_POLLIN, 0);
1090
1091	/* copy the fd */
1092	wnew->desc = wsi->desc;
1093
1094	assert(lws_socket_is_valid(wnew->desc.sockfd));
1095
1096	/* disconnect the fd from association with old wsi */
1097
1098	if (__remove_wsi_socket_from_fds(wsi))
1099		return -1;
1100
1101	sanity_assert_no_wsi_traces(wsi->a.context, wsi);
1102	sanity_assert_no_sockfd_traces(wsi->a.context, wsi->desc.sockfd);
1103	wsi->desc.sockfd = LWS_SOCK_INVALID;
1104
1105	__lws_wsi_remove_from_sul(wsi);
1106
1107	/*
1108	 * ... we're doing some magic here in terms of handing off the socket
1109	 * that has been active to a wsi that has not yet itself been active...
1110	 * depending on the event lib we may need to give a magic spark to the
1111	 * new guy and snuff out the old guy's magic spark at that level as well
1112	 */
1113
1114#if defined(LWS_WITH_EVENT_LIBS)
1115	if (wsi->a.context->event_loop_ops->destroy_wsi)
1116		wsi->a.context->event_loop_ops->destroy_wsi(wsi);
1117	if (wsi->a.context->event_loop_ops->sock_accept)
1118		wsi->a.context->event_loop_ops->sock_accept(wnew);
1119#endif
1120
1121	/* point the fd table entry to new guy */
1122
1123	assert(lws_socket_is_valid(wnew->desc.sockfd));
1124
1125	if (__insert_wsi_socket_into_fds(wsi->a.context, wnew))
1126		return -1;
1127
1128#if defined(LWS_WITH_TLS)
1129	/* pass on the tls */
1130
1131	wnew->tls = wsi->tls;
1132	wsi->tls.client_bio = NULL;
1133	wsi->tls.ssl = NULL;
1134	wsi->tls.use_ssl = 0;
1135#endif
1136
1137	/* take over his copy of his endpoint as an active connection */
1138
1139	if (!wnew->cli_hostname_copy && wsi->cli_hostname_copy) {
1140		wnew->cli_hostname_copy = wsi->cli_hostname_copy;
1141		wsi->cli_hostname_copy = NULL;
1142	}
1143	wnew->keep_warm_secs = wsi->keep_warm_secs;
1144
1145	/*
1146	 * selected queued guy now replaces the original leader on the
1147	 * active client conn list
1148	 */
1149
1150	lws_dll2_remove(&wsi->dll_cli_active_conns);
1151	lws_dll2_add_tail(&wnew->dll_cli_active_conns,
1152			  &wsi->a.vhost->dll_cli_active_conns_owner);
1153
1154	/* move any queued guys to queue on new active conn */
1155
1156	lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
1157				   wsi->dll2_cli_txn_queue_owner.head) {
1158		struct lws *ww = lws_container_of(d, struct lws,
1159					  dll2_cli_txn_queue);
1160
1161		lws_dll2_remove(&ww->dll2_cli_txn_queue);
1162		lws_dll2_add_tail(&ww->dll2_cli_txn_queue,
1163				  &wnew->dll2_cli_txn_queue_owner);
1164
1165	} lws_end_foreach_dll_safe(d, d1);
1166
1167	if (take_vh_lock)
1168		lws_vhost_unlock(wsi->a.vhost);
1169
1170	/*
1171	 * The original leader who passed on all his powers already can die...
1172	 * in the call stack above us there are guys who still want to touch
1173	 * him, so have him die next time around the event loop, not now.
1174	 */
1175
1176	wsi->already_did_cce = 1; /* so the close doesn't trigger a CCE */
1177	lws_set_timeout(wsi, 1, LWS_TO_KILL_ASYNC);
1178
1179	/* after the first one, they can only be coming from the queue */
1180	wnew->transaction_from_pipeline_queue = 1;
1181
1182	lwsl_wsi_notice(wsi, " pipeline queue passed -> %s", lws_wsi_tag(wnew));
1183
1184	*_wsi = wnew; /* inform caller we swapped */
1185
1186	return 1; /* new transaction */
1187}
1188#endif
1189
1190int LWS_WARN_UNUSED_RESULT
1191lws_raw_transaction_completed(struct lws *wsi)
1192{
1193	if (lws_has_buffered_out(wsi)) {
1194		/*
1195		 * ...so he tried to send something large, but it went out
1196		 * as a partial, but he immediately called us to say he wants
1197		 * to close the connection.
1198		 *
1199		 * Defer the close until the last part of the partial is sent.
1200		 *
1201		 */
1202
1203		lwsl_wsi_debug(wsi, "deferring due to partial");
1204		wsi->close_when_buffered_out_drained = 1;
1205		lws_callback_on_writable(wsi);
1206
1207		return 0;
1208	}
1209
1210	return -1;
1211}
1212
1213int
1214lws_bind_protocol(struct lws *wsi, const struct lws_protocols *p,
1215		  const char *reason)
1216{
1217//	if (wsi->a.protocol == p)
1218//		return 0;
1219	const struct lws_protocols *vp = wsi->a.vhost->protocols, *vpo;
1220
1221	if (wsi->a.protocol && wsi->protocol_bind_balance) {
1222		wsi->a.protocol->callback(wsi,
1223		       wsi->role_ops->protocol_unbind_cb[!!lwsi_role_server(wsi)],
1224					wsi->user_space, (void *)reason, 0);
1225		wsi->protocol_bind_balance = 0;
1226	}
1227	if (!wsi->user_space_externally_allocated)
1228		lws_free_set_NULL(wsi->user_space);
1229
1230	lws_same_vh_protocol_remove(wsi);
1231
1232	wsi->a.protocol = p;
1233	if (!p)
1234		return 0;
1235
1236	if (lws_ensure_user_space(wsi))
1237		return 1;
1238
1239	if (p > vp && p < &vp[wsi->a.vhost->count_protocols])
1240		lws_same_vh_protocol_insert(wsi, (int)(p - vp));
1241	else {
1242		int n = wsi->a.vhost->count_protocols;
1243		int hit = 0;
1244
1245		vpo = vp;
1246
1247		while (n--) {
1248			if (p->name && vp->name && !strcmp(p->name, vp->name)) {
1249				hit = 1;
1250				lws_same_vh_protocol_insert(wsi, (int)(vp - vpo));
1251				break;
1252			}
1253			vp++;
1254		}
1255		if (!hit)
1256			lwsl_err("%s: %p is not in vhost '%s' protocols list\n",
1257				 __func__, p, wsi->a.vhost->name);
1258	}
1259
1260	if (wsi->a.protocol->callback(wsi, wsi->role_ops->protocol_bind_cb[
1261				    !!lwsi_role_server(wsi)],
1262				    wsi->user_space, NULL, 0))
1263		return 1;
1264
1265	wsi->protocol_bind_balance = 1;
1266
1267	return 0;
1268}
1269
1270void
1271lws_http_close_immortal(struct lws *wsi)
1272{
1273	struct lws *nwsi;
1274
1275	if (!wsi->mux_substream)
1276		return;
1277
1278	assert(wsi->mux_stream_immortal);
1279	wsi->mux_stream_immortal = 0;
1280
1281	nwsi = lws_get_network_wsi(wsi);
1282	lwsl_wsi_debug(wsi, "%s (%d)", lws_wsi_tag(nwsi),
1283				       nwsi->immortal_substream_count);
1284	assert(nwsi->immortal_substream_count);
1285	nwsi->immortal_substream_count--;
1286	if (!nwsi->immortal_substream_count)
1287		/*
1288		 * since we closed the only immortal stream on this nwsi, we
1289		 * need to reapply a normal timeout regime to the nwsi
1290		 */
1291		lws_set_timeout(nwsi, PENDING_TIMEOUT_HTTP_KEEPALIVE_IDLE,
1292				wsi->a.vhost->keepalive_timeout ?
1293				    wsi->a.vhost->keepalive_timeout : 31);
1294}
1295
1296void
1297lws_mux_mark_immortal(struct lws *wsi)
1298{
1299	struct lws *nwsi;
1300
1301	lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
1302
1303	if (!wsi->mux_substream
1304#if defined(LWS_WITH_CLIENT)
1305			&& !wsi->client_mux_substream
1306#endif
1307	) {
1308		lwsl_wsi_err(wsi, "not mux substream");
1309		return;
1310	}
1311
1312	if (wsi->mux_stream_immortal)
1313		/* only need to handle it once per child wsi */
1314		return;
1315
1316	nwsi = lws_get_network_wsi(wsi);
1317	if (!nwsi)
1318		return;
1319
1320	lwsl_wsi_debug(wsi, "%s (%d)\n", lws_wsi_tag(nwsi),
1321				    nwsi->immortal_substream_count);
1322
1323	wsi->mux_stream_immortal = 1;
1324	assert(nwsi->immortal_substream_count < 255); /* largest count */
1325	nwsi->immortal_substream_count++;
1326	if (nwsi->immortal_substream_count == 1)
1327		lws_set_timeout(nwsi, NO_PENDING_TIMEOUT, 0);
1328}
1329
1330int
1331lws_http_mark_sse(struct lws *wsi)
1332{
1333	if (!wsi)
1334		return 0;
1335
1336	lws_http_headers_detach(wsi);
1337	lws_mux_mark_immortal(wsi);
1338
1339	if (wsi->mux_substream)
1340		wsi->h2_stream_carries_sse = 1;
1341
1342	return 0;
1343}
1344
1345#if defined(LWS_WITH_CLIENT)
1346
1347const char *
1348lws_wsi_client_stash_item(struct lws *wsi, int stash_idx, int hdr_idx)
1349{
1350	/* try the generic client stash */
1351	if (wsi->stash)
1352		return wsi->stash->cis[stash_idx];
1353
1354#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
1355	/* if not, use the ah stash if applicable */
1356	return lws_hdr_simple_ptr(wsi, (enum lws_token_indexes)hdr_idx);
1357#else
1358	return NULL;
1359#endif
1360}
1361#endif
1362
1363#if defined(LWS_ROLE_H2) || defined(LWS_ROLE_MQTT)
1364
1365void
1366lws_wsi_mux_insert(struct lws *wsi, struct lws *parent_wsi, unsigned int sid)
1367{
1368	lwsl_wsi_info(wsi, "par %s: assign sid %d (curr %d)",
1369			lws_wsi_tag(parent_wsi), sid, wsi->mux.my_sid);
1370
1371	if (wsi->mux.my_sid && wsi->mux.my_sid != (unsigned int)sid)
1372		assert(0);
1373
1374	wsi->mux.my_sid = sid;
1375	wsi->mux.parent_wsi = parent_wsi;
1376	wsi->role_ops = parent_wsi->role_ops;
1377
1378	/* new guy's sibling is whoever was the first child before */
1379	wsi->mux.sibling_list = parent_wsi->mux.child_list;
1380
1381	/* first child is now the new guy */
1382	parent_wsi->mux.child_list = wsi;
1383
1384	parent_wsi->mux.child_count++;
1385}
1386
1387struct lws *
1388lws_wsi_mux_from_id(struct lws *parent_wsi, unsigned int sid)
1389{
1390	lws_start_foreach_ll(struct lws *, wsi, parent_wsi->mux.child_list) {
1391		if (wsi->mux.my_sid == sid)
1392			return wsi;
1393	} lws_end_foreach_ll(wsi, mux.sibling_list);
1394
1395	return NULL;
1396}
1397
1398void
1399lws_wsi_mux_dump_children(struct lws *wsi)
1400{
1401#if defined(_DEBUG)
1402	if (!wsi->mux.parent_wsi || !lwsl_visible(LLL_INFO))
1403		return;
1404
1405	lws_start_foreach_llp(struct lws **, w,
1406			      wsi->mux.parent_wsi->mux.child_list) {
1407		lwsl_wsi_info(wsi, "   \\---- child %s %s\n",
1408				   (*w)->role_ops ? (*w)->role_ops->name : "?",
1409							   lws_wsi_tag(*w));
1410		assert(*w != (*w)->mux.sibling_list);
1411	} lws_end_foreach_llp(w, mux.sibling_list);
1412#endif
1413}
1414
1415void
1416lws_wsi_mux_close_children(struct lws *wsi, int reason)
1417{
1418	struct lws *wsi2;
1419	struct lws **w;
1420
1421	if (!wsi->mux.child_list)
1422		return;
1423
1424	w = &wsi->mux.child_list;
1425	while (*w) {
1426		lwsl_wsi_info((*w), "   closing child");
1427		/* disconnect from siblings */
1428		wsi2 = (*w)->mux.sibling_list;
1429		assert (wsi2 != *w);
1430		(*w)->mux.sibling_list = NULL;
1431		(*w)->socket_is_permanently_unusable = 1;
1432		__lws_close_free_wsi(*w, (enum lws_close_status)reason, "mux child recurse");
1433		*w = wsi2;
1434	}
1435}
1436
1437
1438void
1439lws_wsi_mux_sibling_disconnect(struct lws *wsi)
1440{
1441	struct lws *wsi2;
1442
1443	lws_start_foreach_llp(struct lws **, w,
1444			      wsi->mux.parent_wsi->mux.child_list) {
1445
1446		/* disconnect from siblings */
1447		if (*w == wsi) {
1448			wsi2 = (*w)->mux.sibling_list;
1449			(*w)->mux.sibling_list = NULL;
1450			*w = wsi2;
1451			lwsl_wsi_debug(wsi, " disentangled from sibling %s",
1452					    lws_wsi_tag(wsi2));
1453			break;
1454		}
1455	} lws_end_foreach_llp(w, mux.sibling_list);
1456	wsi->mux.parent_wsi->mux.child_count--;
1457
1458	wsi->mux.parent_wsi = NULL;
1459}
1460
1461void
1462lws_wsi_mux_dump_waiting_children(struct lws *wsi)
1463{
1464#if defined(_DEBUG)
1465	lwsl_info("%s: %s: children waiting for POLLOUT service:\n",
1466		  __func__, lws_wsi_tag(wsi));
1467
1468	wsi = wsi->mux.child_list;
1469	while (wsi) {
1470		lwsl_wsi_info(wsi, "  %c sid %u: 0x%x %s %s",
1471			  wsi->mux.requested_POLLOUT ? '*' : ' ',
1472			  wsi->mux.my_sid, lwsi_state(wsi),
1473			  wsi->role_ops->name,
1474			  wsi->a.protocol ? wsi->a.protocol->name : "noprotocol");
1475
1476		wsi = wsi->mux.sibling_list;
1477	}
1478#endif
1479}
1480
1481int
1482lws_wsi_mux_mark_parents_needing_writeable(struct lws *wsi)
1483{
1484	struct lws /* *network_wsi = lws_get_network_wsi(wsi), */ *wsi2;
1485	//int already = network_wsi->mux.requested_POLLOUT;
1486
1487	/* mark everybody above him as requesting pollout */
1488
1489	wsi2 = wsi;
1490	while (wsi2) {
1491		wsi2->mux.requested_POLLOUT = 1;
1492		lwsl_wsi_info(wsi2, "sid %u, pending writable",
1493							wsi2->mux.my_sid);
1494		wsi2 = wsi2->mux.parent_wsi;
1495	}
1496
1497	return 0; // already;
1498}
1499
1500struct lws *
1501lws_wsi_mux_move_child_to_tail(struct lws **wsi2)
1502{
1503	struct lws *w = *wsi2;
1504
1505	while (w) {
1506		if (!w->mux.sibling_list) { /* w is the current last */
1507			lwsl_wsi_debug(w, "*wsi2 = %s\n", lws_wsi_tag(*wsi2));
1508
1509			if (w == *wsi2) /* we are already last */
1510				break;
1511
1512			/* last points to us as new last */
1513			w->mux.sibling_list = *wsi2;
1514
1515			/* guy pointing to us until now points to
1516			 * our old next */
1517			*wsi2 = (*wsi2)->mux.sibling_list;
1518
1519			/* we point to nothing because we are last */
1520			w->mux.sibling_list->mux.sibling_list = NULL;
1521
1522			/* w becomes us */
1523			w = w->mux.sibling_list;
1524			break;
1525		}
1526		w = w->mux.sibling_list;
1527	}
1528
1529	/* clear the waiting for POLLOUT on the guy that was chosen */
1530
1531	if (w)
1532		w->mux.requested_POLLOUT = 0;
1533
1534	return w;
1535}
1536
1537int
1538lws_wsi_mux_action_pending_writeable_reqs(struct lws *wsi)
1539{
1540	struct lws *w = wsi->mux.child_list;
1541
1542	while (w) {
1543		if (w->mux.requested_POLLOUT) {
1544			if (lws_change_pollfd(wsi, 0, LWS_POLLOUT))
1545				return -1;
1546			return 0;
1547		}
1548		w = w->mux.sibling_list;
1549	}
1550
1551	if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
1552		return -1;
1553
1554	return 0;
1555}
1556
1557int
1558lws_wsi_txc_check_skint(struct lws_tx_credit *txc, int32_t tx_cr)
1559{
1560	if (txc->tx_cr <= 0) {
1561		/*
1562		 * If other side is not able to cope with us sending any DATA
1563		 * so no matter if we have POLLOUT on our side if it's DATA we
1564		 * want to send.
1565		 */
1566
1567		if (!txc->skint)
1568			lwsl_info("%s: %p: skint (%d)\n", __func__, txc,
1569				  (int)txc->tx_cr);
1570
1571		txc->skint = 1;
1572
1573		return 1;
1574	}
1575
1576	if (txc->skint)
1577		lwsl_info("%s: %p: unskint (%d)\n", __func__, txc,
1578			  (int)txc->tx_cr);
1579
1580	txc->skint = 0;
1581
1582	return 0;
1583}
1584
1585#if defined(_DEBUG)
1586void
1587lws_wsi_txc_describe(struct lws_tx_credit *txc, const char *at, uint32_t sid)
1588{
1589	lwsl_info("%s: %p: %s: sid %d: %speer-to-us: %d, us-to-peer: %d\n",
1590		  __func__, txc, at, (int)sid, txc->skint ? "SKINT, " : "",
1591		  (int)txc->peer_tx_cr_est, (int)txc->tx_cr);
1592}
1593#endif
1594
1595int
1596lws_wsi_tx_credit(struct lws *wsi, char peer_to_us, int add)
1597{
1598	if (wsi->role_ops && lws_rops_fidx(wsi->role_ops, LWS_ROPS_tx_credit))
1599		return lws_rops_func_fidx(wsi->role_ops, LWS_ROPS_tx_credit).
1600				   tx_credit(wsi, peer_to_us, add);
1601
1602	return 0;
1603}
1604
1605/*
1606 * Let the protocol know about incoming tx credit window updates if it's
1607 * managing the flow control manually (it may want to proxy this information)
1608 */
1609
1610int
1611lws_wsi_txc_report_manual_txcr_in(struct lws *wsi, int32_t bump)
1612{
1613	if (!wsi->txc.manual)
1614		/*
1615		 * If we don't care about managing it manually, no need to
1616		 * report it
1617		 */
1618		return 0;
1619
1620	return user_callback_handle_rxflow(wsi->a.protocol->callback,
1621					   wsi, LWS_CALLBACK_WSI_TX_CREDIT_GET,
1622					   wsi->user_space, NULL, (size_t)bump);
1623}
1624
1625#if defined(LWS_WITH_CLIENT)
1626
1627int
1628lws_wsi_mux_apply_queue(struct lws *wsi)
1629{
1630	/* we have a transaction queue that wants to pipeline */
1631
1632	lws_context_lock(wsi->a.context, __func__); /* -------------- cx { */
1633	lws_vhost_lock(wsi->a.vhost);
1634
1635	lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
1636				   wsi->dll2_cli_txn_queue_owner.head) {
1637		struct lws *w = lws_container_of(d, struct lws,
1638						 dll2_cli_txn_queue);
1639
1640#if defined(LWS_ROLE_H2)
1641		if (lwsi_role_http(wsi) &&
1642		    lwsi_state(w) == LRS_H2_WAITING_TO_SEND_HEADERS) {
1643			lwsl_wsi_info(w, "cli pipeq to be h2");
1644
1645			lwsi_set_state(w, LRS_H1C_ISSUE_HANDSHAKE2);
1646
1647			/* remove ourselves from client queue */
1648			lws_dll2_remove(&w->dll2_cli_txn_queue);
1649
1650			/* attach ourselves as an h2 stream */
1651			lws_wsi_h2_adopt(wsi, w);
1652		}
1653#endif
1654
1655#if defined(LWS_ROLE_MQTT)
1656		if (lwsi_role_mqtt(wsi) &&
1657		    lwsi_state(wsi) == LRS_ESTABLISHED) {
1658			lwsl_wsi_info(w, "cli pipeq to be mqtt\n");
1659
1660			/* remove ourselves from client queue */
1661			lws_dll2_remove(&w->dll2_cli_txn_queue);
1662
1663			/* attach ourselves as an h2 stream */
1664			lws_wsi_mqtt_adopt(wsi, w);
1665		}
1666#endif
1667
1668	} lws_end_foreach_dll_safe(d, d1);
1669
1670	lws_vhost_unlock(wsi->a.vhost);
1671	lws_context_unlock(wsi->a.context); /* } cx --------------  */
1672
1673	return 0;
1674}
1675
1676#endif
1677
1678#endif
1679