1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-30 00:00:16 +01:00
libwebsockets/lib/core-net/private.h
Andy Green d1d313b4bf ws proxy: also proxy h1 ws to h1 and h2
lws has been able to proxy h2 or h1 inbound connections to an
h1 onward connection for a while now.  It's simple to use just
build with LWS_WITH_HTTP_PROXY and make a mount where the origin
is the onward connection details.  Unix sockets can also be
used as the onward connection.

This patch extends the support to be able to also do the same for
inbound h2 or h1 ws upgrades to an h1 ws onward connection as well.

This allows you to offer completely different services in a
common URL space, including ones that connect back by ws / wss.
2019-03-21 10:26:47 +08:00

1069 lines
27 KiB
C

/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
*
* 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
*/
#if !defined(__LWS_CORE_NET_PRIVATE_H__)
#define __LWS_CORE_NET_PRIVATE_H__
#include "roles/private.h"
#ifdef LWS_WITH_IPV6
#if defined(WIN32) || defined(_WIN32)
#include <wincrypt.h>
#include <iphlpapi.h>
#else
#include <net/if.h>
#endif
#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 */
};
/*
*
* ------ roles ------
*
*/
/* 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 }}
/*
*
* ------ event_loop ops ------
*
*/
/* 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),
};
enum lws_parser_return {
LPR_OK = 0,
LPR_FAIL = -1,
LPR_DO_FALLBACK = 2,
LPR_FORBIDDEN = -2
};
typedef union {
#ifdef LWS_WITH_IPV6
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
uint8_t af;
};
#endif
enum {
LWS_EV_READ = (1 << 0),
LWS_EV_WRITE = (1 << 1),
LWS_EV_START = (1 << 2),
LWS_EV_STOP = (1 << 3),
LWS_EV_PREPARE_DELETION = (1u << 31),
};
#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))
#else
#define LWS_IPV6_ENABLED(context) (0)
#endif
#ifdef LWS_WITH_UNIX_SOCK
#define LWS_UNIX_SOCK_ENABLED(vhost) \
(vhost->options & LWS_SERVER_OPTION_UNIX_SOCK)
#else
#define LWS_UNIX_SOCK_ENABLED(vhost) (0)
#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;
char *alpn;
void *opaque_user_data; /* not allocated or freed by lws */
};
#endif
#define lws_wsi_is_udp(___wsi) (!!___wsi->udp)
#define LWS_H2_FRAME_HEADER_LENGTH 9
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;
int tsi_req;
};
/*
* so we can have n connections being serviced simultaneously,
* these things need to be isolated per-thread.
*/
struct lws_context_per_thread {
#if LWS_MAX_SMP > 1
pthread_mutex_t lock_stats;
struct lws_mutex_refcount mr;
pthread_t self;
#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 dll_timeout_head;
struct lws_dll dll_hrtimer_head;
struct lws_dll dll_head_buflist; /* guys with pending rxflow */
#if defined(LWS_WITH_TLS)
struct lws_pt_tls tls;
#endif
struct lws_pollfd *fds;
volatile struct lws_foreign_thread_pollfd * volatile foreign_pfd_list;
#ifdef _WIN32
WSAEVENT events;
#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;
#endif
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
struct lws_pt_role_http http;
#endif
#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;
#endif
#if defined(LWS_WITH_LIBUV)
struct lws_pt_eventlibs_libuv uv;
#endif
#if defined(LWS_WITH_LIBEVENT)
struct lws_pt_eventlibs_libevent event;
#endif
#if defined(LWS_WITH_LIBEV) || defined(LWS_WITH_LIBUV) || \
defined(LWS_WITH_LIBEVENT)
struct lws_signal_watcher w_sigint;
#endif
/* --- */
unsigned long count_conns;
unsigned int fds_count;
/*
* 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;
};
struct lws_conn_stats {
unsigned long long rx, tx;
unsigned long h1_conn, h1_trans, h2_trans, ws_upg, h2_alpn, h2_subs,
h2_upg, rejected;
};
/*
* virtual host -related context information
* vhostwide SSL context
* vhostwide proxy
*
* hierarchy:
*
* 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
*/
struct lws_vhost {
#if !defined(LWS_WITHOUT_CLIENT)
char proxy_basic_auth_token[128];
#endif
#if LWS_MAX_SMP > 1
pthread_mutex_t lock;
char close_flow_vs_tsi[LWS_MAX_SMP];
#endif
#if defined(LWS_ROLE_H2)
struct lws_vhost_role_h2 h2;
#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)
struct lws_vhost_role_ws ws;
#endif
#if defined(LWS_WITH_SOCKS5)
char socks_proxy_address[128];
char socks_user[96];
char socks_password[96];
#endif
#if defined(LWS_WITH_LIBEV)
struct lws_io_watcher w_accept;
#endif
struct lws_conn_stats conn_stats;
struct lws_context *context;
struct lws_vhost *vhost_next;
struct lws *lserv_wsi;
const char *name;
const char *iface;
const char *listen_accept_role;
const char *listen_accept_protocol;
void (*finalize)(struct lws_vhost *vh, void *arg);
void *finalize_arg;
#if !defined(LWS_WITH_ESP32) && !defined(OPTEE_TA) && !defined(WIN32)
int bind_iface;
#endif
const struct lws_protocols *protocols;
void **protocol_vh_privs;
const struct lws_protocol_vhost_options *pvo;
const struct lws_protocol_vhost_options *headers;
struct lws_dll *same_vh_protocol_heads;
struct lws_vhost *no_listener_vhost_list;
#if !defined(LWS_NO_CLIENT)
struct lws_dll dll_cli_active_conns_head;
#endif
#if defined(LWS_WITH_TLS)
struct lws_vhost_tls tls;
#endif
struct lws_timed_vh_protocol *timed_vh_protocol_list;
void *user;
int listen_port;
#if defined(LWS_WITH_SOCKS5)
unsigned int socks_proxy_port;
#endif
unsigned int options;
int count_protocols;
int ka_time;
int ka_probes;
int ka_interval;
int keepalive_timeout;
int timeout_secs_ah_idle;
int count_bound_wsi;
#ifdef LWS_WITH_ACCESS_LOG
int log_fd;
#endif
unsigned int allocated_vhost_protocols:1;
unsigned int created_vhost_protocols:1;
unsigned int being_destroyed:1;
unsigned char default_protocol_index;
unsigned char raw_protocol_index;
};
void
__lws_vhost_destroy2(struct lws_vhost *vh);
struct lws {
/* 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;
#endif
#if defined(LWS_ROLE_WS)
struct _lws_websocket_related *ws; /* allocated if we upgrade to ws */
#endif
#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;
#endif
#if defined(LWS_WITH_LIBEV) || defined(LWS_WITH_LIBEVENT)
struct lws_io_watcher w_write;
#endif
/* pointers */
struct lws_context *context;
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 same_vh_protocol;
struct lws_dll dll_timeout;
struct lws_dll dll_hrtimer;
struct lws_dll dll_buflist; /* guys with pending rxflow */
#if defined(LWS_WITH_THREADPOOL)
struct lws_threadpool_task *tp_task;
#endif
#if defined(LWS_WITH_PEER_LIMITS)
struct lws_peer *peer;
#endif
struct lws_udp *udp;
#ifndef LWS_NO_CLIENT
struct client_info_stash *stash;
char *cli_hostname_copy;
struct lws_dll dll_cli_active_conns;
struct lws_dll2_owner dll2_cli_txn_queue_owner;
struct lws_dll2 dll2_cli_txn_queue;
#endif
void *user_space;
void *opaque_parent_data;
void *opaque_user_data;
struct lws_buflist *buflist; /* input-side buflist */
struct lws_buflist *buflist_out; /* output-side buflist */
#if defined(LWS_WITH_TLS)
struct lws_lws_tls tls;
#endif
lws_sock_file_fd_type desc; /* .filefd / .sockfd */
#if defined(LWS_WITH_STATS)
uint64_t active_writable_req_us;
#if defined(LWS_WITH_TLS)
uint64_t accept_start_us;
#endif
#endif
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)
int position_in_fds_table;
#ifndef LWS_NO_CLIENT
int chunk_remaining;
#endif
unsigned int cache_secs;
unsigned int hdr_parsing_completed:1;
unsigned int http2_substream:1;
unsigned int upgraded_to_http2:1;
unsigned int h2_stream_carries_ws:1;
unsigned int h2_stream_carries_sse:1;
unsigned int seen_nonpseudoheader:1;
unsigned int listener:1;
unsigned int user_space_externally_allocated:1;
unsigned int socket_is_permanently_unusable:1;
unsigned int rxflow_change_to:2;
unsigned int conn_stat_done:1;
unsigned int cache_reuse:1;
unsigned int cache_revalidate:1;
unsigned int cache_intermediaries:1;
unsigned int favoured_pollin:1;
unsigned int sending_chunked:1;
unsigned int interpreting:1;
unsigned int already_did_cce:1;
unsigned int told_user_closed:1;
unsigned int told_event_loop_closed:1;
unsigned int waiting_to_send_close_frame:1;
unsigned int close_needs_ack:1;
unsigned int ipv6:1;
unsigned int parent_pending_cb_on_writable:1;
unsigned int cgi_stdout_zero_length:1;
unsigned int seen_zero_length_recv:1;
unsigned int rxflow_will_be_applied:1;
unsigned int event_pipe:1;
unsigned int handling_404:1;
unsigned int protocol_bind_balance:1;
unsigned int unix_skt:1;
unsigned int close_when_buffered_out_drained:1;
unsigned int h1_ws_proxied;
unsigned int proxied_ws_parent;
unsigned int could_have_pending:1; /* detect back-to-back writes */
unsigned int outer_will_close:1;
unsigned int shadow:1; /* we do not control fd lifecycle at all */
#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 */
unsigned int client_rx_avail:1;
unsigned int client_http_body_pending:1;
unsigned int transaction_from_pipeline_queue:1;
unsigned int keepalive_active:1;
unsigned int keepalive_rejected:1;
unsigned int client_pipeline:1;
unsigned int client_h2_alpn:1;
unsigned int client_h2_substream:1;
#endif
#ifdef _WIN32
unsigned int sock_send_blocking:1;
#endif
#ifndef LWS_NO_CLIENT
unsigned short c_port;
#endif
unsigned short pending_timeout_limit;
/* chars */
char lws_rx_parse_state; /* enum lws_rx_parse_state */
char rx_frame_type; /* enum lws_write_protocol */
char pending_timeout; /* enum pending_timeout */
char tsi; /* thread service index we belong to */
char protocol_interpret_idx;
char redirects;
uint8_t rxflow_bitmap;
uint8_t bound_vhost_index;
#ifdef LWS_WITH_CGI
char cgi_channel; /* which of stdin/out/err */
char hdr_state;
#endif
#ifndef LWS_NO_CLIENT
char chunk_parser; /* enum lws_chunk_parser */
#endif
#if defined(LWS_WITH_CGI) || !defined(LWS_NO_CLIENT)
char reason_bf; /* internal writeable callback reason bitfield */
#endif
#if defined(LWS_WITH_STATS) && defined(LWS_WITH_TLS)
char seen_rx;
#endif
uint8_t immortal_substream_count;
/* volatile to make sure code is aware other thread can change */
volatile char handling_pollout;
volatile char leave_pollout_active;
#if LWS_MAX_SMP > 1
volatile char undergoing_init_from_other_pt;
#endif
};
#define lws_is_flowcontrolled(w) (!!(wsi->rxflow_bitmap))
void
lws_service_do_ripe_rxflow(struct lws_context_per_thread *pt);
const struct lws_role_ops *
lws_role_by_name(const char *name);
LWS_EXTERN int
lws_socket_bind(struct lws_vhost *vhost, lws_sockfd_type sockfd, int port,
const char *iface, int ipv6_allowed);
#if defined(LWS_WITH_IPV6)
LWS_EXTERN unsigned long
lws_get_addr_scope(const char *ipaddr);
#endif
LWS_EXTERN void
lws_close_free_wsi(struct lws *wsi, enum lws_close_status, const char *caller);
LWS_EXTERN void
__lws_close_free_wsi(struct lws *wsi, enum lws_close_status, const char *caller);
LWS_EXTERN void
__lws_free_wsi(struct lws *wsi);
#if LWS_MAX_SMP > 1
static LWS_INLINE void
lws_pt_mutex_init(struct lws_context_per_thread *pt)
{
lws_mutex_refcount_init(&pt->mr);
pthread_mutex_init(&pt->lock_stats, NULL);
}
static LWS_INLINE void
lws_pt_mutex_destroy(struct lws_context_per_thread *pt)
{
pthread_mutex_destroy(&pt->lock_stats);
lws_mutex_refcount_destroy(&pt->mr);
}
#define lws_pt_lock(pt, reason) lws_mutex_refcount_lock(&pt->mr, reason)
#define lws_pt_unlock(pt) lws_mutex_refcount_unlock(&pt->mr)
static LWS_INLINE void
lws_pt_stats_lock(struct lws_context_per_thread *pt)
{
pthread_mutex_lock(&pt->lock_stats);
}
static LWS_INLINE void
lws_pt_stats_unlock(struct lws_context_per_thread *pt)
{
pthread_mutex_unlock(&pt->lock_stats);
}
#endif
/*
* EXTENSIONS
*/
#if defined(LWS_WITHOUT_EXTENSIONS)
#define lws_any_extension_handled(_a, _b, _c, _d) (0)
#define lws_ext_cb_active(_a, _b, _c, _d) (0)
#define lws_ext_cb_all_exts(_a, _b, _c, _d, _e) (0)
#define lws_issue_raw_ext_access lws_issue_raw
#define lws_context_init_extensions(_a, _b)
#endif
LWS_EXTERN int LWS_WARN_UNUSED_RESULT
lws_client_interpret_server_handshake(struct lws *wsi);
LWS_EXTERN int LWS_WARN_UNUSED_RESULT
lws_ws_rx_sm(struct lws *wsi, char already_processed, unsigned char c);
LWS_EXTERN int LWS_WARN_UNUSED_RESULT
lws_issue_raw_ext_access(struct lws *wsi, unsigned char *buf, size_t len);
LWS_EXTERN void
lws_role_transition(struct lws *wsi, enum lwsi_role role, enum lwsi_state state,
const struct lws_role_ops *ops);
int
lws_http_to_fallback(struct lws *wsi, unsigned char *buf, size_t len);
LWS_EXTERN int LWS_WARN_UNUSED_RESULT
user_callback_handle_rxflow(lws_callback_function, struct lws *wsi,
enum lws_callback_reasons reason, void *user,
void *in, size_t len);
LWS_EXTERN int
lws_plat_set_nonblocking(int fd);
LWS_EXTERN int
lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd,
int unix_skt);
LWS_EXTERN int
lws_plat_check_connection_error(struct lws *wsi);
LWS_EXTERN int LWS_WARN_UNUSED_RESULT
lws_header_table_attach(struct lws *wsi, int autoservice);
LWS_EXTERN int
lws_header_table_detach(struct lws *wsi, int autoservice);
LWS_EXTERN int
__lws_header_table_detach(struct lws *wsi, int autoservice);
LWS_EXTERN void
lws_header_table_reset(struct lws *wsi, int autoservice);
void
__lws_header_table_reset(struct lws *wsi, int autoservice);
LWS_EXTERN char * LWS_WARN_UNUSED_RESULT
lws_hdr_simple_ptr(struct lws *wsi, enum lws_token_indexes h);
LWS_EXTERN int LWS_WARN_UNUSED_RESULT
lws_hdr_simple_create(struct lws *wsi, enum lws_token_indexes h, const char *s);
LWS_EXTERN int LWS_WARN_UNUSED_RESULT
lws_ensure_user_space(struct lws *wsi);
LWS_EXTERN int
lws_change_pollfd(struct lws *wsi, int _and, int _or);
#ifndef LWS_NO_SERVER
int _lws_vhost_init_server(const struct lws_context_creation_info *info,
struct lws_vhost *vhost);
LWS_EXTERN struct lws_vhost *
lws_select_vhost(struct lws_context *context, int port, const char *servername);
LWS_EXTERN int LWS_WARN_UNUSED_RESULT
lws_parse_ws(struct lws *wsi, unsigned char **buf, size_t len);
LWS_EXTERN void
lws_server_get_canonical_hostname(struct lws_context *context,
const struct lws_context_creation_info *info);
#else
#define _lws_vhost_init_server(_a, _b) (0)
#define lws_parse_ws(_a, _b, _c) (0)
#define lws_server_get_canonical_hostname(_a, _b)
#endif
LWS_EXTERN int
__remove_wsi_socket_from_fds(struct lws *wsi);
LWS_EXTERN int
lws_rxflow_cache(struct lws *wsi, unsigned char *buf, int n, int len);
LWS_EXTERN int
lws_service_flag_pending(struct lws_context *context, int tsi);
LWS_EXTERN void
lws_client_stash_destroy(struct lws *wsi);
static LWS_INLINE int
lws_has_buffered_out(struct lws *wsi) { return !!wsi->buflist_out; }
LWS_EXTERN int LWS_WARN_UNUSED_RESULT
lws_ws_client_rx_sm(struct lws *wsi, unsigned char c);
LWS_EXTERN int LWS_WARN_UNUSED_RESULT
lws_parse(struct lws *wsi, unsigned char *buf, int *len);
LWS_EXTERN int LWS_WARN_UNUSED_RESULT
lws_parse_urldecode(struct lws *wsi, uint8_t *_c);
LWS_EXTERN int LWS_WARN_UNUSED_RESULT
lws_http_action(struct lws *wsi);
LWS_EXTERN void
__lws_close_free_wsi_final(struct lws *wsi);
LWS_EXTERN void
lws_libuv_closehandle(struct lws *wsi);
LWS_EXTERN int
lws_libuv_check_watcher_active(struct lws *wsi);
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);
struct lws *
lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd);
void
lws_vhost_bind_wsi(struct lws_vhost *vh, struct lws *wsi);
void
lws_vhost_unbind_wsi(struct lws *wsi);
void
__lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs);
int
__lws_change_pollfd(struct lws *wsi, int _and, int _or);
int
lws_callback_as_writeable(struct lws *wsi);
int
lws_role_call_client_bind(struct lws *wsi,
const struct lws_client_connect_info *i);
void
lws_remove_child_from_any_parent(struct lws *wsi);
char *
lws_generate_client_ws_handshake(struct lws *wsi, char *p, const char *conn1);
int
lws_client_ws_upgrade(struct lws *wsi, const char **cce);
int
lws_create_client_ws_object(const struct lws_client_connect_info *i,
struct lws *wsi);
int
lws_alpn_comma_to_openssl(const char *comma, uint8_t *os, int len);
int
lws_role_call_alpn_negotiated(struct lws *wsi, const char *alpn);
int
lws_tls_server_conn_alpn(struct lws *wsi);
int
lws_ws_client_rx_sm_block(struct lws *wsi, unsigned char **buf, size_t len);
void
lws_destroy_event_pipe(struct lws *wsi);
/* socks */
void socks_generate_msg(struct lws *wsi, enum socks_msg_type type,
ssize_t *msg_len);
void
lws_sum_stats(const struct lws_context *ctx, struct lws_conn_stats *cs);
LWS_EXTERN int
__lws_timed_callback_remove(struct lws_vhost *vh, struct lws_timed_vh_protocol *p);
LWS_EXTERN int LWS_WARN_UNUSED_RESULT
__insert_wsi_socket_into_fds(struct lws_context *context, struct lws *wsi);
LWS_EXTERN int LWS_WARN_UNUSED_RESULT
lws_issue_raw(struct lws *wsi, unsigned char *buf, size_t len);
LWS_EXTERN void
lws_remove_from_timeout_list(struct lws *wsi);
LWS_EXTERN struct lws * LWS_WARN_UNUSED_RESULT
lws_client_connect_2(struct lws *wsi);
LWS_VISIBLE struct lws * LWS_WARN_UNUSED_RESULT
lws_client_reset(struct lws **wsi, int ssl, const char *address, int port,
const char *path, const char *host);
LWS_EXTERN struct lws * LWS_WARN_UNUSED_RESULT
lws_create_new_server_wsi(struct lws_vhost *vhost, int fixed_tsi);
LWS_EXTERN char * LWS_WARN_UNUSED_RESULT
lws_generate_client_handshake(struct lws *wsi, char *pkt);
LWS_EXTERN int
lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd);
LWS_EXTERN struct lws *
lws_http_client_connect_via_info2(struct lws *wsi);
#ifndef LWS_NO_CLIENT
LWS_EXTERN int lws_client_socket_service(struct lws *wsi,
struct lws_pollfd *pollfd,
struct lws *wsi_conn);
LWS_EXTERN struct lws *
lws_client_wsi_effective(struct lws *wsi);
LWS_EXTERN int LWS_WARN_UNUSED_RESULT
lws_http_transaction_completed_client(struct lws *wsi);
#if !defined(LWS_WITH_TLS)
#define lws_context_init_client_ssl(_a, _b) (0)
#endif
LWS_EXTERN void
lws_decode_ssl_error(void);
#else
#define lws_context_init_client_ssl(_a, _b) (0)
#endif
LWS_EXTERN int
__lws_rx_flow_control(struct lws *wsi);
LWS_EXTERN int
_lws_change_pollfd(struct lws *wsi, int _and, int _or, struct lws_pollargs *pa);
#ifndef LWS_NO_SERVER
LWS_EXTERN int
lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len);
#else
#define lws_server_socket_service(_b, _c) (0)
#define lws_handshake_server(_a, _b, _c) (0)
#endif
#ifdef LWS_WITH_ACCESS_LOG
LWS_EXTERN int
lws_access_log(struct lws *wsi);
LWS_EXTERN void
lws_prepare_access_log_info(struct lws *wsi, char *uri_ptr, int len, int meth);
#else
#define lws_access_log(_a)
#endif
LWS_EXTERN int
lws_cgi_kill_terminated(struct lws_context_per_thread *pt);
LWS_EXTERN void
lws_cgi_remove_and_kill(struct lws *wsi);
LWS_EXTERN void
lws_plat_delete_socket_from_fds(struct lws_context *context,
struct lws *wsi, int m);
LWS_EXTERN void
lws_plat_insert_socket_into_fds(struct lws_context *context,
struct lws *wsi);
LWS_EXTERN void
lws_plat_service_periodic(struct lws_context *context);
LWS_EXTERN int
lws_plat_change_pollfd(struct lws_context *context, struct lws *wsi,
struct lws_pollfd *pfd);
int
lws_plat_pipe_create(struct lws *wsi);
int
lws_plat_pipe_signal(struct lws *wsi);
void
lws_plat_pipe_close(struct lws *wsi);
LWS_EXTERN void
lws_add_wsi_to_draining_ext_list(struct lws *wsi);
LWS_EXTERN void
lws_remove_wsi_from_draining_ext_list(struct lws *wsi);
LWS_EXTERN int
lws_poll_listen_fd(struct lws_pollfd *fd);
LWS_EXTERN int
lws_plat_service(struct lws_context *context, int timeout_ms);
LWS_EXTERN LWS_VISIBLE int
_lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi);
LWS_EXTERN int
lws_pthread_self_to_tsi(struct lws_context *context);
LWS_EXTERN const char * LWS_WARN_UNUSED_RESULT
lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt);
LWS_EXTERN int LWS_WARN_UNUSED_RESULT
lws_plat_inet_pton(int af, const char *src, void *dst);
LWS_EXTERN void
lws_same_vh_protocol_remove(struct lws *wsi);
LWS_EXTERN void
__lws_same_vh_protocol_remove(struct lws *wsi);
LWS_EXTERN void
lws_same_vh_protocol_insert(struct lws *wsi, int n);
LWS_EXTERN int
lws_broadcast(struct lws_context *context, int reason, void *in, size_t len);
#if defined(LWS_WITH_STATS)
void
lws_stats_atomic_bump(struct lws_context * context,
struct lws_context_per_thread *pt, int index, uint64_t bump);
void
lws_stats_atomic_max(struct lws_context * context,
struct lws_context_per_thread *pt, int index, uint64_t val);
#else
static LWS_INLINE uint64_t lws_stats_atomic_bump(struct lws_context * context,
struct lws_context_per_thread *pt, int index, uint64_t bump) {
(void)context; (void)pt; (void)index; (void)bump; return 0; }
static LWS_INLINE uint64_t lws_stats_atomic_max(struct lws_context * context,
struct lws_context_per_thread *pt, int index, uint64_t val) {
(void)context; (void)pt; (void)index; (void)val; return 0; }
#endif
#if defined(LWS_WITH_PEER_LIMITS)
void
lws_peer_track_wsi_close(struct lws_context *context, struct lws_peer *peer);
int
lws_peer_confirm_ah_attach_ok(struct lws_context *context,
struct lws_peer *peer);
void
lws_peer_track_ah_detach(struct lws_context *context, struct lws_peer *peer);
void
lws_peer_cull_peer_wait_list(struct lws_context *context);
struct lws_peer *
lws_get_or_create_peer(struct lws_vhost *vhost, lws_sockfd_type sockfd);
void
lws_peer_add_wsi(struct lws_context *context, struct lws_peer *peer,
struct lws *wsi);
void
lws_peer_dump_from_wsi(struct lws *wsi);
#endif
#ifdef LWS_WITH_HUBBUB
hubbub_error
html_parser_cb(const hubbub_token *token, void *pw);
#endif
int
lws_threadpool_tsi_context(struct lws_context *context, int tsi);
void
__lws_remove_from_timeout_list(struct lws *wsi);
lws_usec_t
__lws_hrtimer_service(struct lws_context_per_thread *pt);
int
lws_buflist_aware_read(struct lws_context_per_thread *pt, struct lws *wsi,
struct lws_tokens *ebuf);
int
lws_buflist_aware_consume(struct lws *wsi, struct lws_tokens *ebuf, int used,
int buffered);
#ifdef __cplusplus
};
#endif
#endif