Skip to content
Snippets Groups Projects
private.h 39 KiB
Newer Older
  • Learn to ignore specific revisions
  • Andy Green's avatar
    Andy Green committed
    /*
     * libwebsockets - small server side websockets and web server implementation
    
    Andy Green's avatar
    Andy Green committed
     *
    
     * Copyright (C) 2010 - 2018 Andy Green <andy@warmcat.com>
    
    Andy Green's avatar
    Andy Green committed
     *
     *  This library is free software; you can redistribute it and/or
     *  modify it under the terms of the GNU Lesser General Public
     *  License as published by the Free Software Foundation:
     *  version 2.1 of the License.
     *
     *  This library is distributed in the hope that it will be useful,
     *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     *  Lesser General Public License for more details.
     *
     *  You should have received a copy of the GNU Lesser General Public
     *  License along with this library; if not, write to the Free Software
     *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
     *  MA  02110-1301  USA
     */
    
    #include "lws_config.h"
    
    #include "lws_config_private.h"
    
    Andy Green's avatar
    Andy Green committed
    #if defined(LWS_WITH_CGI) && defined(LWS_HAVE_VFORK)
    
     #define  _GNU_SOURCE
    
    Andy Green's avatar
    Andy Green committed
    #endif
    
    
    #if defined(__COVERITY__) && !defined(LWS_COVERITY_WORKAROUND)
     #define LWS_COVERITY_WORKAROUND
     typedef float _Float32;
     typedef float _Float64;
     typedef float _Float128;
     typedef float _Float32x;
     typedef float _Float64x;
     typedef float _Float128x;
    
    Andy Green's avatar
    Andy Green committed
    #endif
    
    
    Andy Green's avatar
    Andy Green committed
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #include <time.h>
    
    Andy Green's avatar
    Andy Green committed
    #include <ctype.h>
    
    Peter Young's avatar
    Peter Young committed
    #include <limits.h>
    
    #include <stdarg.h>
    
    #include <inttypes.h>
    
    #include <assert.h>
    
    #ifdef LWS_HAVE_SYS_TYPES_H
    
     #include <sys/types.h>
    
    #ifdef LWS_HAVE_SYS_STAT_H
    
     #include <sys/stat.h>
    
    emironov's avatar
    emironov committed
    #endif
    
    
    #if LWS_MAX_SMP > 1
     #include <pthread.h>
    
    Andy Green's avatar
    Andy Green committed
    #ifndef LWS_DEF_HEADER_LEN
    
    #define LWS_DEF_HEADER_LEN 4096
    
    Andy Green's avatar
    Andy Green committed
    #ifndef LWS_DEF_HEADER_POOL
    
    #define LWS_DEF_HEADER_POOL 4
    
    #ifndef LWS_MAX_PROTOCOLS
    
    #define LWS_MAX_PROTOCOLS 5
    
    #endif
    #ifndef LWS_MAX_EXTENSIONS_ACTIVE
    
    Andy Green's avatar
    Andy Green committed
    #define LWS_MAX_EXTENSIONS_ACTIVE 1
    
    #ifndef LWS_MAX_EXT_OFFERS
    #define LWS_MAX_EXT_OFFERS 8
    #endif
    
    #ifndef SPEC_LATEST_SUPPORTED
    
    #define SPEC_LATEST_SUPPORTED 13
    
    #endif
    #ifndef AWAITING_TIMEOUT
    
    Andy Green's avatar
    Andy Green committed
    #define AWAITING_TIMEOUT 20
    
    #endif
    #ifndef CIPHERS_LIST_STRING
    
    #define CIPHERS_LIST_STRING "DEFAULT"
    
    #ifndef LWS_SOMAXCONN
    #define LWS_SOMAXCONN SOMAXCONN
    #endif
    
    #define MAX_WEBSOCKET_04_KEY_LEN 128
    
    
    #ifndef SYSTEM_RANDOM_FILEPATH
    
    #define SYSTEM_RANDOM_FILEPATH "/dev/urandom"
    
    #define LWS_H2_RX_SCRATCH_SIZE 512
    
    
    #define lws_socket_is_valid(x) (x != LWS_SOCK_INVALID)
    
    #ifndef LWS_HAVE_STRERROR
     #define strerror(x) ""
    #endif
    
     /*
      *
      *  ------ private platform defines ------
      *
      */
    
    #if defined(LWS_WITH_ESP32)
     #include "plat/esp32/private.h"
    #else
     #if defined(WIN32) || defined(_WIN32)
      #include "plat/windows/private.h"
     #else
      #if defined(LWS_PLAT_OPTEE)
       #include "plat/optee/private.h"
      #else
       #include "plat/unix/private.h"
      #endif
     #endif
    #endif
    
    
    #ifndef LWS_HAVE_BZERO
     #ifndef bzero
      #define bzero(b, len) (memset((b), '\0', (len)), (void) 0)
     #endif
    #endif
    
    
     /*
      *
      *  ------ public api ------
      *
      */
    
    #include "libwebsockets.h"
    
    
    #include "tls/private.h"
    
    
    #if defined(WIN32) || defined(_WIN32)
    	 // Visual studio older than 2015 and WIN_CE has only _stricmp
    	#if (defined(_MSC_VER) && _MSC_VER < 1900) || defined(_WIN32_WCE)
    	#define strcasecmp _stricmp
    	#elif !defined(__MINGW32__)
    	#define strcasecmp stricmp
    	#endif
    	#define getdtablesize() 30000
    #endif
    
    #ifndef LWS_ARRAY_SIZE
    #define LWS_ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
    #endif
    
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    
    /*
     * All lws_tls...() functions must return this type, converting the
     * native backend result and doing the extra work to determine which one
     * as needed.
     *
     * Native TLS backend return codes are NOT ALLOWED outside the backend.
     *
     * Non-SSL mode also uses these types.
     */
    enum lws_ssl_capable_status {
    
    	LWS_SSL_CAPABLE_ERROR			= -1, /* it failed */
    	LWS_SSL_CAPABLE_DONE			= 0,  /* it succeeded */
    	LWS_SSL_CAPABLE_MORE_SERVICE_READ	= -2, /* retry WANT_READ */
    	LWS_SSL_CAPABLE_MORE_SERVICE_WRITE	= -3, /* retry WANT_WRITE */
    	LWS_SSL_CAPABLE_MORE_SERVICE		= -4, /* general retry */
    
    #if defined(__clang__)
    #define lws_memory_barrier() __sync_synchronize()
    #elif defined(__GNUC__)
    #define lws_memory_barrier() __sync_synchronize()
    #else
    #define lws_memory_barrier()
    #endif
    
    
    Andy Green's avatar
    Andy Green committed
    
    
    /* null-terminated array of pointers to roles lws built with */
    extern const struct lws_role_ops *available_roles[];
    
    #define LWS_FOR_EVERY_AVAILABLE_ROLE_START(xx) { \
    		const struct lws_role_ops **ppxx = available_roles; \
    		while (*ppxx) { \
    			const struct lws_role_ops *xx = *ppxx++;
    
    #define LWS_FOR_EVERY_AVAILABLE_ROLE_END }}
    
    
    /* enums of socks version */
    enum socks_version {
    	SOCKS_VERSION_4 = 4,
    	SOCKS_VERSION_5 = 5
    };
    
    /* enums of subnegotiation version */
    enum socks_subnegotiation_version {
    	SOCKS_SUBNEGOTIATION_VERSION_1 = 1,
    };
    
    /* enums of socks commands */
    enum socks_command {
    	SOCKS_COMMAND_CONNECT = 1,
    	SOCKS_COMMAND_BIND = 2,
    	SOCKS_COMMAND_UDP_ASSOCIATE = 3
    };
    
    /* enums of socks address type */
    enum socks_atyp {
    	SOCKS_ATYP_IPV4 = 1,
    	SOCKS_ATYP_DOMAINNAME = 3,
    	SOCKS_ATYP_IPV6 = 4
    };
    
    /* enums of socks authentication methods */
    enum socks_auth_method {
    	SOCKS_AUTH_NO_AUTH = 0,
    	SOCKS_AUTH_GSSAPI = 1,
    	SOCKS_AUTH_USERNAME_PASSWORD = 2
    };
    
    /* enums of subnegotiation status */
    enum socks_subnegotiation_status {
    	SOCKS_SUBNEGOTIATION_STATUS_SUCCESS = 0,
    };
    
    /* enums of socks request reply */
    enum socks_request_reply {
    	SOCKS_REQUEST_REPLY_SUCCESS = 0,
    	SOCKS_REQUEST_REPLY_FAILURE_GENERAL = 1,
    	SOCKS_REQUEST_REPLY_CONNECTION_NOT_ALLOWED = 2,
    	SOCKS_REQUEST_REPLY_NETWORK_UNREACHABLE = 3,
    	SOCKS_REQUEST_REPLY_HOST_UNREACHABLE = 4,
    	SOCKS_REQUEST_REPLY_CONNECTION_REFUSED = 5,
    	SOCKS_REQUEST_REPLY_TTL_EXPIRED = 6,
    	SOCKS_REQUEST_REPLY_COMMAND_NOT_SUPPORTED = 7,
    	SOCKS_REQUEST_REPLY_ATYP_NOT_SUPPORTED = 8
    };
    
    /* enums used to generate socks messages */
    enum socks_msg_type {
    	/* greeting */
    	SOCKS_MSG_GREETING,
    	/* credential, user name and password */
    	SOCKS_MSG_USERNAME_PASSWORD,
    	/* connect command */
    	SOCKS_MSG_CONNECT
    };
    
    
    enum {
    	LWS_RXFLOW_ALLOW = (1 << 0),
    	LWS_RXFLOW_PENDING_CHANGE = (1 << 1),
    };
    
    
    struct lws_ring {
    	void *buf;
    	void (*destroy_element)(void *element);
    
    	uint32_t buflen;
    	uint32_t element_len;
    
    	uint32_t head;
    	uint32_t oldest_tail;
    };
    
    
    struct lws_protocols;
    struct lws;
    
    Andrew Canaday's avatar
    Andrew Canaday committed
    struct lws_io_watcher {
    
    #ifdef LWS_WITH_LIBEV
    
    	struct lws_io_watcher_libev ev;
    
    Andy Green's avatar
    Andy Green committed
    #endif
    
    #ifdef LWS_WITH_LIBUV
    
    	struct lws_io_watcher_libuv uv;
    
    #ifdef LWS_WITH_LIBEVENT
    
    	struct lws_io_watcher_libevent event;
    
    Andy Green's avatar
    Andy Green committed
    #endif
    	struct lws_context *context;
    
    
    	uint8_t actual_events;
    
    Andrew Canaday's avatar
    Andrew Canaday committed
    };
    
    struct lws_signal_watcher {
    
    #ifdef LWS_WITH_LIBEV
    
    	struct lws_signal_watcher_libev ev;
    
    Andy Green's avatar
    Andy Green committed
    #endif
    
    #ifdef LWS_WITH_LIBUV
    
    	struct lws_signal_watcher_libuv uv;
    
    #ifdef LWS_WITH_LIBEVENT
    
    	struct lws_signal_watcher_libevent event;
    
    Andy Green's avatar
    Andy Green committed
    #endif
    	struct lws_context *context;
    
    Andrew Canaday's avatar
    Andrew Canaday committed
    };
    
    
    struct lws_foreign_thread_pollfd {
    	struct lws_foreign_thread_pollfd *next;
    	int fd_index;
    	int _and;
    	int _or;
    };
    
    
    Andy Green's avatar
    Andy Green committed
    #if LWS_MAX_SMP > 1
    
    struct lws_mutex_refcount {
    	pthread_mutex_t lock;
    	pthread_t lock_owner;
    	const char *last_lock_reason;
    	char lock_depth;
    	char metadata;
    };
    
    void
    lws_mutex_refcount_init(struct lws_mutex_refcount *mr);
    
    void
    lws_mutex_refcount_destroy(struct lws_mutex_refcount *mr);
    
    void
    lws_mutex_refcount_lock(struct lws_mutex_refcount *mr, const char *reason);
    
    void
    lws_mutex_refcount_unlock(struct lws_mutex_refcount *mr);
    #endif
    
    #define LWS_HRTIMER_NOWAIT (0x7fffffffffffffffll)
    
    
    Andy Green's avatar
    Andy Green committed
    /*
     * so we can have n connections being serviced simultaneously,
     * these things need to be isolated per-thread.
     */
    
    struct lws_context_per_thread {
    
    Andy Green's avatar
    Andy Green committed
    #if LWS_MAX_SMP > 1
    
    Andy Green's avatar
    Andy Green committed
    	pthread_mutex_t lock_stats;
    
    Andy Green's avatar
    Andy Green committed
    	struct lws_mutex_refcount mr;
    
    Andy Green's avatar
    Andy Green committed
    #endif
    
    
    	struct lws_context *context;
    
    	/*
    	 * usable by anything in the service code, but only if the scope
    	 * does not last longer than the service action (since next service
    	 * of any socket can likewise use it and overwrite)
    	 */
    	unsigned char *serv_buf;
    
    	struct lws_dll_lws dll_head_timeout;
    	struct lws_dll_lws dll_head_hrtimer;
    	struct lws_dll_lws dll_head_buflist; /* guys with pending rxflow */
    
    #if defined(LWS_WITH_TLS)
    
    Andy Green's avatar
    Andy Green committed
    	struct lws_pollfd *fds;
    
    	volatile struct lws_foreign_thread_pollfd * volatile foreign_pfd_list;
    
    #endif
    	lws_sockfd_type dummy_pipe_fds[2];
    	struct lws *pipe_wsi;
    
    	/* --- role based members --- */
    
    #if defined(LWS_ROLE_WS) && !defined(LWS_WITHOUT_EXTENSIONS)
    	struct lws_pt_role_ws ws;
    
    #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
    	struct lws_pt_role_http http;
    #endif
    
    Andy Green's avatar
    Andy Green committed
    #if defined(LWS_ROLE_DBUS)
    	struct lws_pt_role_dbus dbus;
    #endif
    
    	/* --- event library based members --- */
    
    #if defined(LWS_WITH_LIBEV)
    
    	struct lws_pt_eventlibs_libev ev;
    
    Andy Green's avatar
    Andy Green committed
    #endif
    
    #if defined(LWS_WITH_LIBUV)
    
    	struct lws_pt_eventlibs_libuv uv;
    
    Andy Green's avatar
    Andy Green committed
    #endif
    
    #if defined(LWS_WITH_LIBEVENT)
    
    	struct lws_pt_eventlibs_libevent event;
    
    #if defined(LWS_WITH_LIBEV) || defined(LWS_WITH_LIBUV) || \
        defined(LWS_WITH_LIBEVENT)
    
    Andy Green's avatar
    Andy Green committed
    	struct lws_signal_watcher w_sigint;
    
    Andy Green's avatar
    Andy Green committed
    #endif
    
    
    Andy Green's avatar
    Andy Green committed
    	unsigned long count_conns;
    
    	/*
    	 * set to the Thread ID that's doing the service loop just before entry
    	 * to poll indicates service thread likely idling in poll()
    	 * volatile because other threads may check it as part of processing
    	 * for pollfd event change.
    	 */
    	volatile int service_tid;
    	int service_tid_detected;
    
    
    	volatile unsigned char inside_poll;
    	volatile unsigned char foreign_spinlock;
    
    
    	unsigned char tid;
    
    	unsigned char inside_service:1;
    
    	unsigned char event_loop_foreign:1;
    	unsigned char event_loop_destroy_processing_done:1;
    
    Andy Green's avatar
    Andy Green committed
    struct lws_conn_stats {
    	unsigned long long rx, tx;
    
    Andy Green's avatar
    Andy Green committed
    	unsigned long h1_conn, h1_trans, h2_trans, ws_upg, h2_alpn, h2_subs,
    		      h2_upg, rejected;
    
    Andy Green's avatar
    Andy Green committed
    };
    
    void
    lws_sum_stats(const struct lws_context *ctx, struct lws_conn_stats *cs);
    
    
    struct lws_timed_vh_protocol {
    	struct lws_timed_vh_protocol *next;
    	const struct lws_protocols *protocol;
    
    	struct lws_vhost *vhost; /* only used for pending processing */
    
    	time_t time;
    	int reason;
    
    Andy Green's avatar
    Andy Green committed
    /*
     * virtual host -related context information
     *   vhostwide SSL context
     *   vhostwide proxy
     *
    
    Andy Green's avatar
    Andy Green committed
     *
     * context -> vhost -> wsi
     *
     * incoming connection non-SSL vhost binding:
     *
     *    listen socket -> wsi -> select vhost after first headers
     *
     * incoming connection SSL vhost binding:
     *
     *    SSL SNI -> wsi -> bind after SSL negotiation
     */
    
    
    Andy Green's avatar
    Andy Green committed
    struct lws_vhost {
    
    #if !defined(LWS_WITHOUT_CLIENT)
    
    Andy Green's avatar
    Andy Green committed
    	char proxy_basic_auth_token[128];
    
    Andy Green's avatar
    Andy Green committed
    #if LWS_MAX_SMP > 1
    	pthread_mutex_t lock;
    
    	char close_flow_vs_tsi[LWS_MAX_SMP];
    
    Andy Green's avatar
    Andy Green committed
    #endif
    
    Andy Green's avatar
    Andy Green committed
    #endif
    
    #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
    	struct lws_vhost_role_http http;
    #endif
    
    #if defined(LWS_ROLE_WS) && !defined(LWS_WITHOUT_EXTENSIONS)
    
    #if defined(LWS_WITH_SOCKS5)
    	char socks_proxy_address[128];
    	char socks_user[96];
    	char socks_password[96];
    
    Andy Green's avatar
    Andy Green committed
    #endif
    #if defined(LWS_WITH_LIBEV)
    	struct lws_io_watcher w_accept;
    
    Andy Green's avatar
    Andy Green committed
    #endif
    
    Andy Green's avatar
    Andy Green committed
    	struct lws_conn_stats conn_stats;
    
    Andy Green's avatar
    Andy Green committed
    	struct lws_context *context;
    	struct lws_vhost *vhost_next;
    
    Andy Green's avatar
    Andy Green committed
    	struct lws *lserv_wsi;
    	const char *name;
    	const char *iface;
    
    	void (*finalize)(struct lws_vhost *vh, void *arg);
    	void *finalize_arg;
    
    
    Andy Green's avatar
    Andy Green committed
    #if !defined(LWS_WITH_ESP32) && !defined(OPTEE_TA) && !defined(WIN32)
    
    Andy Green's avatar
    Andy Green committed
    	const struct lws_protocols *protocols;
    
    Andy Green's avatar
    Andy Green committed
    	void **protocol_vh_privs;
    
    	const struct lws_protocol_vhost_options *pvo;
    
    	const struct lws_protocol_vhost_options *headers;
    
    	struct lws_dll_lws *same_vh_protocol_heads;
    
    	struct lws_vhost *no_listener_vhost_list;
    
    Andy Green's avatar
    Andy Green committed
    #if !defined(LWS_NO_CLIENT)
    	struct lws_dll_lws dll_active_client_conns;
    #endif
    
    Andy Green's avatar
    Andy Green committed
    #if defined(LWS_WITH_TLS)
    
    Andy Green's avatar
    Andy Green committed
    #endif
    
    	struct lws_timed_vh_protocol *timed_vh_protocol_list;
    
    Andy Green's avatar
    Andy Green committed
    
    	int listen_port;
    
    #if defined(LWS_WITH_SOCKS5)
    	unsigned int socks_proxy_port;
    #endif
    
    	unsigned int options;
    
    Andy Green's avatar
    Andy Green committed
    	int count_protocols;
    	int ka_time;
    	int ka_probes;
    	int ka_interval;
    
    Andy Green's avatar
    Andy Green committed
    	int keepalive_timeout;
    
    	int timeout_secs_ah_idle;
    
    #ifdef LWS_WITH_ACCESS_LOG
    	int log_fd;
    #endif
    
    Andy Green's avatar
    Andy Green committed
    
    
    	unsigned int created_vhost_protocols:1;
    
    Andy Green's avatar
    Andy Green committed
    	unsigned int being_destroyed:1;
    
    	unsigned char default_protocol_index;
    
    	unsigned char raw_protocol_index;
    
    Andy Green's avatar
    Andy Green committed
    };
    
    
    void
    lws_vhost_bind_wsi(struct lws_vhost *vh, struct lws *wsi);
    void
    lws_vhost_unbind_wsi(struct lws *wsi);
    void
    
    __lws_vhost_destroy2(struct lws_vhost *vh);
    
    Andy Green's avatar
    Andy Green committed
    struct lws_deferred_free
    {
    	struct lws_deferred_free *next;
    	time_t deadline;
    	void *payload;
    };
    
    
    Andy Green's avatar
    Andy Green committed
    typedef union {
    
    #ifdef LWS_WITH_IPV6
    
    Andy Green's avatar
    Andy Green committed
    	struct sockaddr_in6 sa6;
    #endif
    	struct sockaddr_in sa4;
    } sockaddr46;
    
    
    #if defined(LWS_WITH_PEER_LIMITS)
    struct lws_peer {
    	struct lws_peer *next;
    	struct lws_peer *peer_wait_list;
    
    	time_t time_created;
    	time_t time_closed_all;
    
    	uint8_t addr[32];
    	uint32_t hash;
    	uint32_t count_wsi;
    	uint32_t total_wsi;
    
    
    #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
    	struct lws_peer_role_http http;
    #endif
    
    Andy Green's avatar
    Andy Green committed
    
    	uint8_t af;
    };
    #endif
    
    
    Andy Green's avatar
    Andy Green committed
    /*
     * the rest is managed per-context, that includes
     *
     *  - processwide single fd -> wsi lookup
     *  - contextwide headers pool
     */
    
    struct lws_context {
    	time_t last_timeout_check_s;
    
    	time_t last_ws_ping_pong_check_s;
    
    Andy Green's avatar
    Andy Green committed
    	time_t time_up;
    
    	time_t time_discontiguity;
    	time_t time_fixup;
    
    Andy Green's avatar
    Andy Green committed
    	struct lws_plat_file_ops fops_platform;
    
    	struct lws_context **pcontext_finalize;
    
    Andy Green's avatar
    Andy Green committed
    #if defined(LWS_WITH_HTTP2)
    	struct http2_settings set;
    #endif
    
    Andy Green's avatar
    Andy Green committed
    #if defined(LWS_WITH_ZIP_FOPS)
    	struct lws_plat_file_ops fops_zip;
    #endif
    
    Andy Green's avatar
    Andy Green committed
    	struct lws_context_per_thread pt[LWS_MAX_SMP];
    
    Andy Green's avatar
    Andy Green committed
    	struct lws_conn_stats conn_stats;
    
    Andy Green's avatar
    Andy Green committed
    #if LWS_MAX_SMP > 1
    
    Andy Green's avatar
    Andy Green committed
    	struct lws_mutex_refcount mr;
    
    Andy Green's avatar
    Andy Green committed
    #endif
    
    #ifdef _WIN32
    /* different implementation between unix and windows */
    
    	struct lws_fd_hashtable fd_hashtable[FD_HASHTABLE_MODULUS];
    
    	struct lws **lws_lookup;  /* fd to wsi */
    
    Andy Green's avatar
    Andy Green committed
    	struct lws_vhost *vhost_list;
    
    	struct lws_vhost *no_listener_vhost_list;
    
    Andy Green's avatar
    Andy Green committed
    	struct lws_vhost *vhost_pending_destruction_list;
    
    Andy Green's avatar
    Andy Green committed
    	struct lws_plugin *plugin_list;
    
    Andy Green's avatar
    Andy Green committed
    	struct lws_deferred_free *deferred_free_list;
    
    Andy Green's avatar
    Andy Green committed
    
    #if defined(LWS_WITH_THREADPOOL)
    	struct lws_threadpool *tp_list_head;
    #endif
    
    
    Andy Green's avatar
    Andy Green committed
    #if defined(LWS_WITH_PEER_LIMITS)
    	struct lws_peer **pl_hash_table;
    	struct lws_peer *peer_wait_list;
    	time_t next_cull;
    #endif
    
    Andy Green's avatar
    Andy Green committed
    
    
    	void *external_baggage_free_on_destroy;
    
    	const struct lws_token_limits *token_limits;
    	void *user_space;
    
    	const struct lws_protocol_vhost_options *reject_service_keywords;
    
    Andy Green's avatar
    Andy Green committed
    	lws_reload_func deprecation_cb;
    
    	void (*eventlib_signal_cb)(void *event_lib_handle, int signum);
    
    Andy Green's avatar
    Andy Green committed
    #if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
    	cap_value_t caps[4];
    	char count_caps;
    #endif
    
    
    #if defined(LWS_WITH_LIBEV)
    
    	struct lws_context_eventlibs_libev ev;
    
    Andy Green's avatar
    Andy Green committed
    #endif
    
    #if defined(LWS_WITH_LIBUV)
    
    	struct lws_context_eventlibs_libuv uv;
    
    #if defined(LWS_WITH_LIBEVENT)
    
    	struct lws_context_eventlibs_libevent event;
    
    Andy Green's avatar
    Andy Green committed
    #endif
    
    	struct lws_event_loop_ops *event_loop_ops;
    
    
    
    #if defined(LWS_WITH_TLS)
    	struct lws_context_tls tls;
    #endif
    
    
    	char canonical_hostname[128];
    
    #ifdef LWS_LATENCY
    	unsigned long worst_latency;
    	char worst_latency_info[256];
    #endif
    
    
    Andy Green's avatar
    Andy Green committed
    #if defined(LWS_WITH_STATS)
    	uint64_t lws_stats[LWSSTATS_SIZE];
    	uint64_t last_dump;
    	int updated;
    #endif
    
    Andy Green's avatar
    Andy Green committed
    #if defined(LWS_WITH_ESP32)
    	unsigned long time_last_state_dump;
    	uint32_t last_free_heap;
    #endif
    
    Andy Green's avatar
    Andy Green committed
    
    
    	int max_fds;
    
    	int count_event_loop_static_asset_handles;
    
    Andy Green's avatar
    Andy Green committed
    	int started_with_parent;
    
    Andy Green's avatar
    Andy Green committed
    	int uid, gid;
    
    Andy Green's avatar
    Andy Green committed
    
    
    	int fd_random;
    
    Andy Green's avatar
    Andy Green committed
    	int count_wsi_allocated;
    
    Andy Green's avatar
    Andy Green committed
    	int count_cgi_spawned;
    
    	unsigned int options;
    
    Andy Green's avatar
    Andy Green committed
    	unsigned int fd_limit_per_thread;
    
    Andy Green's avatar
    Andy Green committed
    	unsigned int timeout_secs;
    
    	int simultaneous_ssl_restriction;
    	int simultaneous_ssl;
    
    Andy Green's avatar
    Andy Green committed
    #if defined(LWS_WITH_PEER_LIMITS)
    	uint32_t pl_hash_elements;	/* protected by context->lock */
    	uint32_t count_peers;		/* protected by context->lock */
    	unsigned short ip_limit_ah;
    	unsigned short ip_limit_wsi;
    #endif
    
    Andy Green's avatar
    Andy Green committed
    	unsigned int deprecated:1;
    	unsigned int being_destroyed:1;
    	unsigned int being_destroyed1:1;
    
    	unsigned int being_destroyed2:1;
    
    Andy Green's avatar
    Andy Green committed
    	unsigned int requested_kill:1;
    	unsigned int protocol_init_done:1;
    
    	unsigned int doing_protocol_init:1;
    	unsigned int done_protocol_destroy_cb:1;
    	unsigned int finalize_destroy_after_internal_loops_stopped:1;
    
    Andy Green's avatar
    Andy Green committed
    	short count_threads;
    
    Andy Green's avatar
    Andy Green committed
    	short plugin_protocol_count;
    	short plugin_extension_count;
    
    	short server_string_len;
    
    	unsigned short ws_ping_pong_interval;
    
    Andy Green's avatar
    Andy Green committed
    	unsigned short deprecation_pending_listen_close_count;
    
    Andy Green's avatar
    Andy Green committed
    
    
    Andy Green's avatar
    Andy Green committed
    	uint8_t max_fi;
    
    Andy Green's avatar
    Andy Green committed
    int
    
    lws_check_deferred_free(struct lws_context *context, int tsi, int force);
    
    Andy Green's avatar
    Andy Green committed
    
    
    Andy Green's avatar
    Andy Green committed
    #define lws_get_context_protocol(ctx, x) ctx->vhost_list->protocols[x]
    #define lws_get_vh_protocol(vh, x) vh->protocols[x]
    
    
    Andy Green's avatar
    Andy Green committed
    LWS_EXTERN void
    
    Andy Green's avatar
    Andy Green committed
    __lws_close_free_wsi_final(struct lws *wsi);
    
    Andy Green's avatar
    Andy Green committed
    LWS_EXTERN void
    lws_libuv_closehandle(struct lws *wsi);
    
    LWS_EXTERN int
    lws_libuv_check_watcher_active(struct lws *wsi);
    
    Andy Green's avatar
    Andy Green committed
    
    
    LWS_VISIBLE LWS_EXTERN int
    
    lws_plat_plugins_init(struct lws_context * context, const char * const *d);
    
    
    LWS_VISIBLE LWS_EXTERN int
    lws_plat_plugins_destroy(struct lws_context * context);
    
    
    LWS_EXTERN void
    lws_restart_ws_ping_pong_timer(struct lws *wsi);
    
    
    Andy Green's avatar
    Andy Green committed
    struct lws *
    lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd);
    
    
    int
    lws_jws_base64_enc(const char *in, size_t in_len, char *out, size_t out_max);
    
    
    void
    lws_vhost_destroy1(struct lws_vhost *vh);
    
    enum {
    	LWS_EV_READ = (1 << 0),
    	LWS_EV_WRITE = (1 << 1),
    	LWS_EV_START = (1 << 2),
    	LWS_EV_STOP = (1 << 3),
    
    Andy Green's avatar
    Andy Green committed
    
    
    Andy Green's avatar
    Andy Green committed
    	LWS_EV_PREPARE_DELETION = (1u << 31),
    
    Andy Green's avatar
    Andy Green committed
    
    
    #if defined(LWS_WITH_ESP32)
    LWS_EXTERN int
    
    lws_find_string_in_file(const char *filename, const char *str, int stringlen);
    
    #ifdef LWS_WITH_IPV6
    
    #define LWS_IPV6_ENABLED(vh) \
    
    	(!lws_check_opt(vh->context->options, LWS_SERVER_OPTION_DISABLE_IPV6) && \
    
    	 !lws_check_opt(vh->options, LWS_SERVER_OPTION_DISABLE_IPV6))
    
    James Devine's avatar
    James Devine committed
    #else
    #define LWS_IPV6_ENABLED(context) (0)
    #endif
    
    Andrew Canaday's avatar
    Andrew Canaday committed
    
    
    #ifdef LWS_WITH_UNIX_SOCK
    
    #define LWS_UNIX_SOCK_ENABLED(vhost) \
    	(vhost->options & LWS_SERVER_OPTION_UNIX_SOCK)
    
    Yeonjun Lim's avatar
    Yeonjun Lim committed
    #else
    
    #define LWS_UNIX_SOCK_ENABLED(vhost) (0)
    
    Yeonjun Lim's avatar
    Yeonjun Lim committed
    #endif
    
    enum uri_path_states {
    	URIPS_IDLE,
    	URIPS_SEEN_SLASH,
    	URIPS_SEEN_SLASH_DOT,
    	URIPS_SEEN_SLASH_DOT_DOT,
    };
    
    enum uri_esc_states {
    	URIES_IDLE,
    	URIES_SEEN_PERCENT,
    	URIES_SEEN_PERCENT_H1,
    };
    
    
    #ifndef LWS_NO_CLIENT
    struct client_info_stash {
    
    	char *address;
    	char *path;
    	char *host;
    	char *origin;
    	char *protocol;
    	char *method;
    	char *iface;
    
    
    signed char char_to_hex(const char c);
    
    Andy Green's avatar
    Andy Green committed
    struct lws_buflist {
    	struct lws_buflist *next;
    
    	size_t len;
    	size_t pos;
    
    	uint8_t buf[1]; /* true length of this is set by the oversize malloc */
    };
    
    
    Andy Green's avatar
    Andy Green committed
    #define lws_wsi_is_udp(___wsi) (!!___wsi->udp)
    
    
    #define LWS_H2_FRAME_HEADER_LENGTH 9
    
    
    	/* structs */
    
    #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
    
    	struct _lws_http_mode_related http;
    
    #endif
    #if defined(LWS_ROLE_H2)
    
    	struct _lws_h2_related h2;
    
    #if defined(LWS_ROLE_WS)
    	struct _lws_websocket_related *ws; /* allocated if we upgrade to ws */
    #endif
    
    Andy Green's avatar
    Andy Green committed
    #if defined(LWS_ROLE_DBUS)
    	struct _lws_dbus_mode_related dbus;
    #endif
    
    	const struct lws_role_ops *role_ops;
    
    	lws_wsi_state_t	wsistate;
    	lws_wsi_state_t wsistate_pre_close;
    
    
    	/* lifetime members */
    
    
    #if defined(LWS_WITH_LIBEV) || defined(LWS_WITH_LIBUV) || \
        defined(LWS_WITH_LIBEVENT)
    
    	struct lws_io_watcher w_read;
    
    Andy Green's avatar
    Andy Green committed
    #endif
    
    #if defined(LWS_WITH_LIBEV) || defined(LWS_WITH_LIBEVENT)
    
    	struct lws_io_watcher w_write;
    
    Andy Green's avatar
    Andy Green committed
    #endif
    
    	struct lws_context *context;
    
    Andy Green's avatar
    Andy Green committed
    	struct lws_vhost *vhost;
    
    	struct lws *parent; /* points to parent, if any */
    	struct lws *child_list; /* points to first child */
    	struct lws *sibling_list; /* subsequent children at same level */
    
    	const struct lws_protocols *protocol;
    
    	struct lws_dll_lws same_vh_protocol;
    
    	struct lws_dll_lws dll_timeout;
    	struct lws_dll_lws dll_hrtimer;
    
    	struct lws_dll_lws dll_buflist; /* guys with pending rxflow */
    
    Andy Green's avatar
    Andy Green committed
    #if defined(LWS_WITH_THREADPOOL)
    	struct lws_threadpool_task *tp_task;
    #endif
    
    
    Andy Green's avatar
    Andy Green committed
    #if defined(LWS_WITH_PEER_LIMITS)
    	struct lws_peer *peer;
    
    Andy Green's avatar
    Andy Green committed
    	struct lws_udp *udp;
    
    Andy Green's avatar
    Andy Green committed
    #ifndef LWS_NO_CLIENT
    	struct client_info_stash *stash;
    
    Andy Green's avatar
    Andy Green committed
    	char *client_hostname_copy;
    
    Andy Green's avatar
    Andy Green committed
    	struct lws_dll_lws dll_active_client_conns;
    	struct lws_dll_lws dll_client_transaction_queue_head;
    	struct lws_dll_lws dll_client_transaction_queue;
    
    Andy Green's avatar
    Andy Green committed
    #endif
    
    Andy Green's avatar
    Andy Green committed
    	void *user_space;
    
    Andy Green's avatar
    Andy Green committed
    	void *opaque_parent_data;
    
    Andy Green's avatar
    Andy Green committed
    
    
    	struct lws_buflist *buflist;		/* input-side buflist */
    	struct lws_buflist *buflist_out;	/* output-side buflist */
    
    Andy Green's avatar
    Andy Green committed
    #if defined(LWS_WITH_TLS)
    
    Andy Green's avatar
    Andy Green committed
    #endif
    
    	lws_sock_file_fd_type desc; /* .filefd / .sockfd */
    
    Andy Green's avatar
    Andy Green committed
    #if defined(LWS_WITH_STATS)
    	uint64_t active_writable_req_us;
    
    Andy Green's avatar
    Andy Green committed
    #if defined(LWS_WITH_TLS)
    
    	uint64_t accept_start_us;
    #endif
    
    Andy Green's avatar
    Andy Green committed
    #endif
    
    Andy Green's avatar
    Andy Green committed
    
    
    	lws_usec_t pending_timer; /* hrtimer fires */
    	time_t pending_timeout_set; /* second-resolution timeout start */
    
    #ifdef LWS_LATENCY
    	unsigned long action_start;
    	unsigned long latency_start;
    #endif
    
    
    	/* ints */
    
    #define LWS_NO_FDS_POS (-1)
    
    Andy Green's avatar
    Andy Green committed
    	int position_in_fds_table;
    
    #ifndef LWS_NO_CLIENT
    	int chunk_remaining;
    #endif
    
    Andy Green's avatar
    Andy Green committed
    	unsigned int cache_secs;
    
    	unsigned int hdr_parsing_completed:1;
    
    Andy Green's avatar
    Andy Green committed
    	unsigned int http2_substream:1;
    
    Andy Green's avatar
    Andy Green committed
    	unsigned int upgraded_to_http2:1;
    
    Andy Green's avatar
    Andy Green committed
    	unsigned int h2_stream_carries_ws:1;
    
    	unsigned int seen_nonpseudoheader:1;
    
    Andy Green's avatar
    Andy Green committed
    	unsigned int listener:1;
    
    	unsigned int user_space_externally_allocated:1;
    
    	unsigned int socket_is_permanently_unusable:1;
    
    Andy Green's avatar
    Andy Green committed
    	unsigned int rxflow_change_to:2;
    
    Andy Green's avatar
    Andy Green committed
    	unsigned int conn_stat_done:1;
    
    Andy Green's avatar
    Andy Green committed
    	unsigned int cache_reuse:1;
    	unsigned int cache_revalidate:1;
    	unsigned int cache_intermediaries:1;
    
    	unsigned int favoured_pollin:1;
    
    Andy Green's avatar
    Andy Green committed
    	unsigned int sending_chunked:1;
    
    	unsigned int interpreting:1;
    
    	unsigned int already_did_cce:1;
    
    	unsigned int told_user_closed:1;
    
    Andy Green's avatar
    Andy Green committed
    	unsigned int told_event_loop_closed:1;
    
    	unsigned int waiting_to_send_close_frame:1;
    
    Andy Green's avatar
    Andy Green committed
    	unsigned int close_needs_ack:1;
    
    	unsigned int ipv6:1;
    
    Andy Green's avatar
    Andy Green committed
    	unsigned int parent_pending_cb_on_writable:1;
    
    	unsigned int cgi_stdout_zero_length:1;
    
    Andy Green's avatar
    Andy Green committed
    	unsigned int seen_zero_length_recv:1;
    	unsigned int rxflow_will_be_applied:1;
    
    	unsigned int event_pipe:1;
    
    Andy Green's avatar
    Andy Green committed
    	unsigned int handling_404:1;
    
    	unsigned int protocol_bind_balance:1;
    
    	unsigned int unix_skt:1;
    
    	unsigned int could_have_pending:1; /* detect back-to-back writes */
    
    	unsigned int outer_will_close:1;
    
    Andy Green's avatar
    Andy Green committed
    	unsigned int shadow:1; /* we do not control fd lifecycle at all */
    
    Andy Green's avatar
    Andy Green committed
    
    
    #ifdef LWS_WITH_ACCESS_LOG
    	unsigned int access_log_pending:1;
    #endif
    
    #ifndef LWS_NO_CLIENT
    	unsigned int do_ws:1; /* whether we are doing http or ws flow */
    
    	unsigned int chunked:1; /* if the clientside connection is chunked */
    
    Andy Green's avatar
    Andy Green committed
    	unsigned int client_rx_avail:1;
    
    	unsigned int client_http_body_pending:1;
    
    Andy Green's avatar
    Andy Green committed
    	unsigned int transaction_from_pipeline_queue:1;
    	unsigned int keepalive_active:1;
    	unsigned int keepalive_rejected:1;
    	unsigned int client_pipeline:1;
    
    Andy Green's avatar
    Andy Green committed
    	unsigned int client_h2_alpn:1;
    	unsigned int client_h2_substream:1;
    
    Andy Green's avatar
    Andy Green committed
    #endif
    
    #ifdef _WIN32
    	unsigned int sock_send_blocking:1;
    #endif
    
    #ifndef LWS_NO_CLIENT
    	unsigned short c_port;
    #endif
    
    	unsigned short pending_timeout_limit;