2 * libwebsockets - small server side websockets and web server implementation
4 * Copyright (C) 2010-2019 Andy Green <andy@warmcat.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation:
9 * version 2.1 of the License.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 #include "private-lib-core.h"
25 void lwsi_set_role(struct lws *wsi, lws_wsi_state_t role)
27 wsi->wsistate = (wsi->wsistate & (~LWSI_ROLE_MASK)) | role;
29 lwsl_debug("lwsi_set_role(%p, 0x%lx)\n", wsi,
30 (unsigned long)wsi->wsistate);
33 void lwsi_set_state(struct lws *wsi, lws_wsi_state_t lrs)
35 wsi->wsistate = (wsi->wsistate & (~LRS_MASK)) | lrs;
37 lwsl_debug("lwsi_set_state(%p, 0x%lx)\n", wsi,
38 (unsigned long)wsi->wsistate);
44 lws_vhost_bind_wsi(struct lws_vhost *vh, struct lws *wsi)
48 lws_context_lock(vh->context, __func__); /* ---------- context { */
50 vh->count_bound_wsi++;
51 lws_context_unlock(vh->context); /* } context ---------- */
52 lwsl_info("%s: vh %s: count_bound_wsi %d\n",
53 __func__, vh->name, vh->count_bound_wsi);
54 assert(wsi->vhost->count_bound_wsi > 0);
58 lws_vhost_unbind_wsi(struct lws *wsi)
63 lws_context_lock(wsi->context, __func__); /* ---------- context { */
65 assert(wsi->vhost->count_bound_wsi > 0);
66 wsi->vhost->count_bound_wsi--;
67 lwsl_info("%s: vh %s: count_bound_wsi %d\n", __func__,
68 wsi->vhost->name, wsi->vhost->count_bound_wsi);
70 if (!wsi->vhost->count_bound_wsi &&
71 wsi->vhost->being_destroyed) {
73 * We have closed all wsi that were bound to this vhost
74 * by any pt: nothing can be servicing any wsi belonging
77 * Finalize the vh destruction
79 __lws_vhost_destroy2(wsi->vhost);
83 lws_context_unlock(wsi->context); /* } context ---------- */
86 LWS_VISIBLE struct lws *
87 lws_get_network_wsi(struct lws *wsi)
92 #if defined(LWS_WITH_HTTP2)
93 if (!wsi->http2_substream
94 #if !defined(LWS_NO_CLIENT)
95 && !wsi->client_h2_substream
100 while (wsi->h2.parent_wsi)
101 wsi = wsi->h2.parent_wsi;
108 LWS_VISIBLE LWS_EXTERN const struct lws_protocols *
109 lws_vhost_name_to_protocol(struct lws_vhost *vh, const char *name)
113 for (n = 0; n < vh->count_protocols; n++)
114 if (vh->protocols[n].name && !strcmp(name, vh->protocols[n].name))
115 return &vh->protocols[n];
121 lws_callback_all_protocol(struct lws_context *context,
122 const struct lws_protocols *protocol, int reason)
124 struct lws_context_per_thread *pt = &context->pt[0];
125 unsigned int n, m = context->count_threads;
129 for (n = 0; n < pt->fds_count; n++) {
130 wsi = wsi_from_fd(context, pt->fds[n].fd);
133 if (wsi->protocol == protocol)
134 protocol->callback(wsi, reason, wsi->user_space,
144 lws_callback_all_protocol_vhost_args(struct lws_vhost *vh,
145 const struct lws_protocols *protocol, int reason,
146 void *argp, size_t len)
148 struct lws_context *context = vh->context;
149 struct lws_context_per_thread *pt = &context->pt[0];
150 unsigned int n, m = context->count_threads;
154 for (n = 0; n < pt->fds_count; n++) {
155 wsi = wsi_from_fd(context, pt->fds[n].fd);
158 if (wsi->vhost == vh && (wsi->protocol == protocol ||
160 wsi->protocol->callback(wsi, reason,
161 wsi->user_space, argp, len);
170 lws_callback_all_protocol_vhost(struct lws_vhost *vh,
171 const struct lws_protocols *protocol, int reason)
173 return lws_callback_all_protocol_vhost_args(vh, protocol, reason, NULL, 0);
176 LWS_VISIBLE LWS_EXTERN int
177 lws_callback_vhost_protocols(struct lws *wsi, int reason, void *in, int len)
181 for (n = 0; n < wsi->vhost->count_protocols; n++)
182 if (wsi->vhost->protocols[n].callback(wsi, reason, NULL, in, len))
188 LWS_VISIBLE LWS_EXTERN int
189 lws_callback_vhost_protocols_vhost(struct lws_vhost *vh, int reason, void *in,
193 struct lws *wsi = lws_zalloc(sizeof(*wsi), "fake wsi");
198 wsi->context = vh->context;
199 lws_vhost_bind_wsi(vh, wsi);
201 for (n = 0; n < wsi->vhost->count_protocols; n++) {
202 wsi->protocol = &vh->protocols[n];
203 if (wsi->protocol->callback(wsi, reason, NULL, in, len)) {
216 lws_rx_flow_control(struct lws *wsi, int _enable)
218 struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
221 // h2 ignores rx flow control atm
222 if (lwsi_role_h2(wsi) || wsi->http2_substream ||
223 lwsi_role_h2_ENCAPSULATION(wsi))
226 lwsl_info("%s: %p 0x%x\n", __func__, wsi, _enable);
228 if (!(_enable & LWS_RXFLOW_REASON_APPLIES)) {
230 * convert user bool style to bitmap style... in user simple
231 * bool style _enable = 0 = flow control it, = 1 = allow rx
233 en = LWS_RXFLOW_REASON_APPLIES | LWS_RXFLOW_REASON_USER_BOOL;
235 en |= LWS_RXFLOW_REASON_APPLIES_ENABLE_BIT;
238 lws_pt_lock(pt, __func__);
240 /* any bit set in rxflow_bitmap DISABLEs rxflow control */
241 if (en & LWS_RXFLOW_REASON_APPLIES_ENABLE_BIT)
242 wsi->rxflow_bitmap &= ~(en & 0xff);
244 wsi->rxflow_bitmap |= en & 0xff;
246 if ((LWS_RXFLOW_PENDING_CHANGE | (!wsi->rxflow_bitmap)) ==
247 wsi->rxflow_change_to)
250 wsi->rxflow_change_to = LWS_RXFLOW_PENDING_CHANGE |
251 (!wsi->rxflow_bitmap);
253 lwsl_info("%s: %p: bitmap 0x%x: en 0x%x, ch 0x%x\n", __func__, wsi,
254 wsi->rxflow_bitmap, en, wsi->rxflow_change_to);
256 if (_enable & LWS_RXFLOW_REASON_FLAG_PROCESS_NOW ||
257 !wsi->rxflow_will_be_applied) {
258 en = __lws_rx_flow_control(wsi);
271 lws_rx_flow_allow_all_protocol(const struct lws_context *context,
272 const struct lws_protocols *protocol)
274 const struct lws_context_per_thread *pt = &context->pt[0];
276 unsigned int n, m = context->count_threads;
279 for (n = 0; n < pt->fds_count; n++) {
280 wsi = wsi_from_fd(context, pt->fds[n].fd);
283 if (wsi->protocol == protocol)
284 lws_rx_flow_control(wsi, LWS_RXFLOW_ALLOW);
290 int user_callback_handle_rxflow(lws_callback_function callback_function,
292 enum lws_callback_reasons reason, void *user,
293 void *in, size_t len)
297 wsi->rxflow_will_be_applied = 1;
298 n = callback_function(wsi, reason, user, in, len);
299 wsi->rxflow_will_be_applied = 0;
301 n = __lws_rx_flow_control(wsi);
307 __lws_rx_flow_control(struct lws *wsi)
309 struct lws *wsic = wsi->child_list;
311 // h2 ignores rx flow control atm
312 if (lwsi_role_h2(wsi) || wsi->http2_substream ||
313 lwsi_role_h2_ENCAPSULATION(wsi))
316 /* if he has children, do those if they were changed */
318 if (wsic->rxflow_change_to & LWS_RXFLOW_PENDING_CHANGE)
319 __lws_rx_flow_control(wsic);
321 wsic = wsic->sibling_list;
324 /* there is no pending change */
325 if (!(wsi->rxflow_change_to & LWS_RXFLOW_PENDING_CHANGE))
328 /* stuff is still buffered, not ready to really accept new input */
329 if (lws_buflist_next_segment_len(&wsi->buflist, NULL)) {
330 /* get ourselves called back to deal with stashed buffer */
331 lws_callback_on_writable(wsi);
335 /* now the pending is cleared, we can change rxflow state */
337 wsi->rxflow_change_to &= ~LWS_RXFLOW_PENDING_CHANGE;
339 lwsl_info("rxflow: wsi %p change_to %d\n", wsi,
340 wsi->rxflow_change_to & LWS_RXFLOW_ALLOW);
342 /* adjust the pollfd for this wsi */
344 if (wsi->rxflow_change_to & LWS_RXFLOW_ALLOW) {
345 lwsl_info("%s: reenable POLLIN\n", __func__);
346 // lws_buflist_describe(&wsi->buflist, NULL);
347 if (__lws_change_pollfd(wsi, 0, LWS_POLLIN)) {
348 lwsl_info("%s: fail\n", __func__);
352 if (__lws_change_pollfd(wsi, LWS_POLLIN, 0))
359 LWS_VISIBLE const struct lws_protocols *
360 lws_get_protocol(struct lws *wsi)
362 return wsi->protocol;
367 lws_ensure_user_space(struct lws *wsi)
372 /* allocate the per-connection user memory (if any) */
374 if (wsi->protocol->per_session_data_size && !wsi->user_space) {
375 wsi->user_space = lws_zalloc(
376 wsi->protocol->per_session_data_size, "user space");
377 if (wsi->user_space == NULL) {
378 lwsl_err("%s: OOM\n", __func__);
382 lwsl_debug("%s: %p protocol pss %lu, user_space=%p\n", __func__,
383 wsi, (long)wsi->protocol->per_session_data_size,
389 lws_adjust_protocol_psds(struct lws *wsi, size_t new_size)
391 ((struct lws_protocols *)lws_get_protocol(wsi))->per_session_data_size =
394 if (lws_ensure_user_space(wsi))
397 return wsi->user_space;
403 lws_is_ssl(struct lws *wsi)
405 #if defined(LWS_WITH_TLS)
406 return wsi->tls.use_ssl & LCCSCF_USE_SSL;
413 #if defined(LWS_WITH_TLS) && !defined(LWS_WITH_MBEDTLS)
414 LWS_VISIBLE lws_tls_conn*
415 lws_get_ssl(struct lws *wsi)
422 lws_partial_buffered(struct lws *wsi)
424 return lws_has_buffered_out(wsi);
427 LWS_VISIBLE lws_fileofs_t
428 lws_get_peer_write_allowance(struct lws *wsi)
430 if (!wsi->role_ops->tx_credit)
432 return wsi->role_ops->tx_credit(wsi);
436 lws_role_transition(struct lws *wsi, enum lwsi_role role, enum lwsi_state state,
437 const struct lws_role_ops *ops)
440 const char *name = "(unset)";
442 wsi->wsistate = role | state;
447 name = wsi->role_ops->name;
448 lwsl_debug("%s: %p: wsistate 0x%lx, ops %s\n", __func__, wsi,
449 (unsigned long)wsi->wsistate, name);
453 LWS_VISIBLE LWS_EXTERN int
454 lws_parse_uri(char *p, const char **prot, const char **ads, int *port,
460 /* cut up the location into address, port and path */
462 while (*p && (*p != ':' || p[1] != '/' || p[2] != '/'))
472 if (*p == '+') /* unix skt */
476 if (!strcmp(*prot, "http") || !strcmp(*prot, "ws"))
478 else if (!strcmp(*prot, "https") || !strcmp(*prot, "wss"))
483 while (*p && *p != ']')
488 while (*p && *p != ':' && (unix_skt || *p != '/'))
494 while (*p && *p != '/')
509 LWS_VISIBLE LWS_EXTERN const char *
510 lws_get_urlarg_by_name(struct lws *wsi, const char *name, char *buf, int len)
512 int n = 0, sl = (int)strlen(name);
514 while (lws_hdr_copy_fragment(wsi, buf, len,
515 WSI_TOKEN_HTTP_URI_ARGS, n) >= 0) {
517 if (!strncmp(buf, name, sl))
527 #if defined(LWS_WITHOUT_EXTENSIONS)
529 /* we need to provide dummy callbacks for internal exts
530 * so user code runs when faced with a lib compiled with
531 * extensions disabled.
535 lws_extension_callback_pm_deflate(struct lws_context *context,
536 const struct lws_extension *ext,
538 enum lws_extension_callback_reasons reason,
539 void *user, void *in, size_t len)
553 lws_set_extension_option(struct lws *wsi, const char *ext_name,
554 const char *opt_name, const char *opt_val)
560 LWS_VISIBLE LWS_EXTERN int
561 lws_is_cgi(struct lws *wsi) {
563 return !!wsi->http.cgi;
569 const struct lws_protocol_vhost_options *
570 lws_pvo_search(const struct lws_protocol_vhost_options *pvo, const char *name)
573 if (!strcmp(pvo->name, name))
583 lws_pvo_get_str(void *in, const char *name, const char **result)
585 const struct lws_protocol_vhost_options *pv =
586 lws_pvo_search((const struct lws_protocol_vhost_options *)in,
592 *result = (const char *)pv->value;
598 lws_broadcast(struct lws_context_per_thread *pt, int reason, void *in, size_t len)
600 struct lws_vhost *v = pt->context->vhost_list;
603 pt->fake_wsi->context = pt->context;
606 const struct lws_protocols *p = v->protocols;
607 pt->fake_wsi->vhost = v; /* not a real bound wsi */
609 for (n = 0; n < v->count_protocols; n++) {
610 pt->fake_wsi->protocol = p;
612 p->callback(pt->fake_wsi, reason, NULL, in, len))
622 LWS_VISIBLE LWS_EXTERN void *
623 lws_wsi_user(struct lws *wsi)
625 return wsi->user_space;
628 LWS_VISIBLE LWS_EXTERN void
629 lws_set_wsi_user(struct lws *wsi, void *data)
631 if (wsi->user_space_externally_allocated)
632 wsi->user_space = data;
634 lwsl_err("%s: Cannot set internally-allocated user_space\n",
638 LWS_VISIBLE LWS_EXTERN struct lws *
639 lws_get_parent(const struct lws *wsi)
644 LWS_VISIBLE LWS_EXTERN struct lws *
645 lws_get_child(const struct lws *wsi)
647 return wsi->child_list;
650 LWS_VISIBLE LWS_EXTERN void *
651 lws_get_opaque_parent_data(const struct lws *wsi)
653 return wsi->opaque_parent_data;
656 LWS_VISIBLE LWS_EXTERN void
657 lws_set_opaque_parent_data(struct lws *wsi, void *data)
659 wsi->opaque_parent_data = data;
662 LWS_VISIBLE LWS_EXTERN void *
663 lws_get_opaque_user_data(const struct lws *wsi)
665 return wsi->opaque_user_data;
668 LWS_VISIBLE LWS_EXTERN void
669 lws_set_opaque_user_data(struct lws *wsi, void *data)
671 wsi->opaque_user_data = data;
674 LWS_VISIBLE LWS_EXTERN int
675 lws_get_child_pending_on_writable(const struct lws *wsi)
677 return wsi->parent_pending_cb_on_writable;
680 LWS_VISIBLE LWS_EXTERN void
681 lws_clear_child_pending_on_writable(struct lws *wsi)
683 wsi->parent_pending_cb_on_writable = 0;
688 LWS_VISIBLE LWS_EXTERN const char *
689 lws_get_vhost_name(struct lws_vhost *vhost)
694 LWS_VISIBLE LWS_EXTERN int
695 lws_get_vhost_port(struct lws_vhost *vhost)
697 return vhost->listen_port;
700 LWS_VISIBLE LWS_EXTERN void *
701 lws_get_vhost_user(struct lws_vhost *vhost)
706 LWS_VISIBLE LWS_EXTERN const char *
707 lws_get_vhost_iface(struct lws_vhost *vhost)
712 LWS_VISIBLE lws_sockfd_type
713 lws_get_socket_fd(struct lws *wsi)
717 return wsi->desc.sockfd;
721 LWS_VISIBLE struct lws_vhost *
722 lws_vhost_get(struct lws *wsi)
727 LWS_VISIBLE struct lws_vhost *
728 lws_get_vhost(struct lws *wsi)
733 LWS_VISIBLE const struct lws_protocols *
734 lws_protocol_get(struct lws *wsi)
736 return wsi->protocol;
739 LWS_VISIBLE const struct lws_udp *
740 lws_get_udp(const struct lws *wsi)
745 LWS_VISIBLE LWS_EXTERN struct lws_context *
746 lws_get_context(const struct lws *wsi)
753 lws_latency(struct lws_context *context, struct lws *wsi, const char *action,
754 int ret, int completed)
756 unsigned long long u;
762 wsi->latency_start = u;
763 if (!wsi->action_start)
764 wsi->action_start = u;
768 if (wsi->action_start == wsi->latency_start)
770 "Completion first try lat %lluus: %p: ret %d: %s\n",
771 u - wsi->latency_start,
772 (void *)wsi, ret, action);
775 "Completion %lluus: lat %lluus: %p: ret %d: %s\n",
776 u - wsi->action_start,
777 u - wsi->latency_start,
778 (void *)wsi, ret, action);
779 wsi->action_start = 0;
781 sprintf(buf, "lat %lluus: %p: ret %d: %s\n",
782 u - wsi->latency_start, (void *)wsi, ret, action);
784 if (u - wsi->latency_start > context->worst_latency) {
785 context->worst_latency = u - wsi->latency_start;
786 strcpy(context->worst_latency_info, buf);
788 lwsl_latency("%s", buf);
792 LWS_VISIBLE int LWS_WARN_UNUSED_RESULT
793 lws_raw_transaction_completed(struct lws *wsi)
795 if (lws_has_buffered_out(wsi)) {
797 * ...so he tried to send something large, but it went out
798 * as a partial, but he immediately called us to say he wants
799 * to close the connection.
801 * Defer the close until the last part of the partial is sent.
804 lwsl_debug("%s: %p: deferring due to partial\n", __func__, wsi);
805 wsi->close_when_buffered_out_drained = 1;
806 lws_callback_on_writable(wsi);
815 lws_bind_protocol(struct lws *wsi, const struct lws_protocols *p,
818 // if (wsi->protocol == p)
820 const struct lws_protocols *vp = wsi->vhost->protocols, *vpo;
822 if (wsi->protocol && wsi->protocol_bind_balance) {
823 wsi->protocol->callback(wsi,
824 wsi->role_ops->protocol_unbind_cb[!!lwsi_role_server(wsi)],
825 wsi->user_space, (void *)reason, 0);
826 wsi->protocol_bind_balance = 0;
828 if (!wsi->user_space_externally_allocated)
829 lws_free_set_NULL(wsi->user_space);
831 lws_same_vh_protocol_remove(wsi);
837 if (lws_ensure_user_space(wsi))
840 if (p > vp && p < &vp[wsi->vhost->count_protocols])
841 lws_same_vh_protocol_insert(wsi, (int)(p - vp));
843 int n = wsi->vhost->count_protocols;
849 if (p->name && vp->name && !strcmp(p->name, vp->name)) {
851 lws_same_vh_protocol_insert(wsi, (int)(vp - vpo));
857 lwsl_err("%s: %p is not in vhost '%s' protocols list\n",
858 __func__, p, wsi->vhost->name);
861 if (wsi->protocol->callback(wsi, wsi->role_ops->protocol_bind_cb[
862 !!lwsi_role_server(wsi)],
863 wsi->user_space, NULL, 0))
866 wsi->protocol_bind_balance = 1;
872 lws_http_mark_sse(struct lws *wsi)
874 lws_http_headers_detach(wsi);
875 lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
877 if (wsi->http2_substream) {
878 struct lws *nwsi = lws_get_network_wsi(wsi);
880 wsi->h2_stream_carries_sse = 1;
881 nwsi->immortal_substream_count++;
882 if (nwsi->immortal_substream_count == 1)
883 lws_set_timeout(nwsi, NO_PENDING_TIMEOUT, 0);