set(LWS_WITHOUT_EXTENSIONS 1)
endif()
-include_directories(include plugins)
+if (LWS_WITH_MBEDTLS)
+ include_directories(lib/tls/mbedtls/wrapper/include)
+endif()
+
+include_directories(include plugins lib/core lib/core-net lib/event-libs include/abstract lib/tls lib/roles lib/event-libs/libuv lib/event-libs/poll lib/event-libs/libevent lib/event-libs/libev lib/jose/jwe lib/jose/jws lib/jose lib/misc lib/roles/http lib/roles/http/compression lib/roles/h1 lib/roles/h2 lib/roles/ws lib/roles/cgi lib/roles/dbus lib/roles/raw-proxy)
+
+if (LWS_WITH_ESP32)
+ include_directories(lib/plat/esp32)
+else()
+ if (WIN32)
+ include_directories(lib/plat/windows)
+ else()
+ if (LWS_WITH_OPTEE)
+ include_directories(lib/plat/optee)
+ else()
+ include_directories(lib/plat/unix)
+ endif()
+ endif()
+endif()
+
if (LWS_WITH_LWSWS)
message(STATUS "LWS_WITH_LWSWS --> Enabling LWS_WITH_PLUGINS and LWS_WITH_LIBUV")
# Group headers and sources.
# Some IDEs use this for nicer file structure.
set(HDR_PRIVATE
- lib/core/private.h)
+ lib/core/private-lib-core.h)
set(HDR_PUBLIC
"${PROJECT_SOURCE_DIR}/include/libwebsockets.h"
list(APPEND SOURCES
lib/core-net/connect.c
lib/core-net/client.c
- lib/roles/http/client/client.c
+ lib/roles/http/client/client-http.c
lib/roles/http/client/client-handshake.c)
endif()
if (LWS_WITH_MBEDTLS)
list(APPEND SOURCES
- lib/tls/mbedtls/tls.c
- lib/tls/mbedtls/x509.c
+ lib/tls/mbedtls/mbedtls-tls.c
+ lib/tls/mbedtls/mbedtls-x509.c
)
if (LWS_WITH_NETWORK)
list(APPEND SOURCES
- lib/tls/mbedtls/ssl.c
+ lib/tls/mbedtls/mbedtls-ssl.c
)
endif()
if (LWS_WITH_GENCRYPTO)
endif()
else()
list(APPEND SOURCES
- lib/tls/openssl/tls.c
- lib/tls/openssl/x509.c
+ lib/tls/openssl/openssl-tls.c
+ lib/tls/openssl/openssl-x509.c
)
if (LWS_WITH_NETWORK)
list(APPEND SOURCES
- lib/tls/openssl/ssl.c
+ lib/tls/openssl/openssl-ssl.c
)
endif()
if (LWS_WITH_GENCRYPTO)
* MA 02110-1301 USA
*/
-#include <core/private.h>
-#include <abstract/private.h>
+#include <private-lib-core.h>
+#include <private-lib-abstract.h>
extern const lws_abs_transport_t lws_abs_transport_cli_raw_skt,
lws_abs_transport_cli_unit_test;
--- /dev/null
+/*
+ * 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
+ */
+
+
+
+
+++ /dev/null
-/*
- * 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
- */
-
-
-
-
* MA 02110-1301 USA
*/
-#include "core/private.h"
-#include "abstract/private.h"
+#include "private-lib-core.h"
+#include "private-lib-abstract.h"
/** enum lwsgs_smtp_states - where we are in SMTP protocol sequence */
typedef enum lwsgs_smtp_states {
* for each test using te
*/
-#include <core/private.h>
+#include <private-lib-core.h>
struct lws_seq_test_sequencer {
lws_abs_t original_abs;
* MA 02110-1301 USA
*/
-#include "core/private.h"
-#include "abstract/private.h"
+#include "private-lib-core.h"
+#include "private-lib-abstract.h"
typedef struct lws_abstxp_raw_skt_priv {
struct lws_abs *abs;
* to provided canned packets from an array of test vectors.
*/
-#include "core/private.h"
-#include "abstract/private.h"
+#include "private-lib-core.h"
+#include "private-lib-abstract.h"
/* this is the transport priv instantiated at abs->ati */
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
static int
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
LWS_VISIBLE int
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
void
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
void
lws_client_stash_destroy(struct lws *wsi)
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
#if defined(LWS_WITH_HTTP_PROXY)
static int
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
struct lws_dsh_search {
size_t required;
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
#if !defined(LWS_WITH_ESP32) && !defined(LWS_PLAT_OPTEE)
static int
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
/*
* notice this returns number of bytes consumed, or -1
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
int
_lws_change_pollfd(struct lws *wsi, int _and, int _or, struct lws_pollargs *pa)
--- /dev/null
+/*
+ * 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__
+
+#if !defined(_POSIX_C_SOURCE)
+#define _POSIX_C_SOURCE 200112L
+#endif
+
+#include "private-lib-roles.h"
+
+#ifdef LWS_WITH_IPV6
+#if defined(WIN32) || defined(_WIN32)
+#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
+};
+
+enum pmd_return {
+ PMDR_UNKNOWN,
+ PMDR_DID_NOTHING,
+ PMDR_HAS_PENDING,
+ PMDR_EMPTY_NONFINAL,
+ PMDR_EMPTY_FINAL,
+
+ PMDR_FAILED = -1
+};
+
+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
+
+int
+__lws_sul_insert(lws_dll2_owner_t *own, lws_sorted_usec_list_t *sul,
+ lws_usec_t us);
+
+lws_usec_t
+__lws_sul_check(lws_dll2_owner_t *own, lws_usec_t usnow);
+
+struct lws_timed_vh_protocol {
+ struct lws_timed_vh_protocol *next;
+ lws_sorted_usec_list_t sul;
+ const struct lws_protocols *protocol;
+ struct lws_vhost *vhost; /* only used for pending processing */
+ int reason;
+ int tsi_req;
+};
+
+/*
+ * lws_dsh
+*/
+
+typedef struct lws_dsh_obj_head {
+ lws_dll2_owner_t owner;
+ int kind;
+} lws_dsh_obj_head_t;
+
+typedef struct lws_dsh lws_dsh_t;
+
+typedef struct lws_dsh_obj {
+ lws_dll2_t list; /* must be first */
+ lws_dsh_t *dsh; /* invalid when on free list */
+ size_t size; /* invalid when on free list */
+ size_t asize;
+} lws_dsh_obj_t;
+
+typedef struct lws_dsh {
+ lws_dll2_t list;
+ uint8_t *buf;
+ lws_dsh_obj_head_t *oha; /* array of object heads/kind */
+ size_t buffer_size;
+ size_t locally_in_use;
+ size_t locally_free;
+ int count_kinds;
+ uint8_t being_destroyed;
+ /*
+ * Overallocations at create:
+ *
+ * - the buffer itself
+ * - the object heads array
+ */
+} lws_dsh_t;
+
+/*
+ * 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_dll2_owner dll_buflist_owner; /* guys with pending rxflow */
+ struct lws_dll2_owner seq_owner; /* list of lws_sequencer-s */
+
+ struct lws_dll2_owner pt_sul_owner;
+
+#if defined (LWS_WITH_SEQUENCER)
+ lws_sorted_usec_list_t sul_seq_heartbeat;
+#endif
+#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
+ lws_sorted_usec_list_t sul_ah_lifecheck;
+#endif
+#if defined(LWS_WITH_TLS) && !defined(LWS_NO_SERVER)
+ lws_sorted_usec_list_t sul_tls;
+#endif
+#if defined(LWS_PLAT_UNIX)
+ lws_sorted_usec_list_t sul_plat;
+#endif
+#if defined(LWS_WITH_STATS)
+ uint64_t lws_stats[LWSSTATS_SIZE];
+ int updated;
+ lws_sorted_usec_list_t sul_stats;
+#endif
+#if defined(LWS_WITH_PEER_LIMITS)
+ lws_sorted_usec_list_t sul_peer_limits;
+#endif
+
+#if defined(LWS_WITH_TLS)
+ struct lws_pt_tls tls;
+#endif
+ struct lws *fake_wsi; /* used for callbacks where there's no wsi */
+
+ 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_pollfd *fds;
+ volatile struct lws_foreign_thread_pollfd * volatile foreign_pfd_list;
+#ifdef _WIN32
+ WSAEVENT events;
+ CRITICAL_SECTION interrupt_lock;
+#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;
+#ifdef _WIN32
+ unsigned char interrupt_requested:1;
+#endif
+};
+
+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;
+ const char *unix_socket_perms;
+
+ 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_dll2_owner *same_vh_protocol_owner;
+ struct lws_vhost *no_listener_vhost_list;
+ struct lws_dll2_owner abstract_instances_owner;
+
+#if !defined(LWS_NO_CLIENT)
+ struct lws_dll2_owner dll_cli_active_conns_owner;
+#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 */
+ lws_sorted_usec_list_t sul_ping;
+#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
+
+ lws_sorted_usec_list_t sul_timeout;
+ lws_sorted_usec_list_t sul_hrtimer;
+
+ /* 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_dll2 same_vh_protocol;
+
+ lws_seq_t *seq; /* associated sequencer if any */
+
+ struct lws_dll2 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_dll2 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
+
+#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
+
+ /* 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_WARN_UNUSED_RESULT
+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);
+
+enum {
+ LWSRXFC_ERROR = -1,
+ LWSRXFC_CACHED = 0,
+ LWSRXFC_ADDITIONAL = 1,
+ LWSRXFC_TRIMMED = 2,
+};
+
+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 */
+int
+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 lws_usec_t
+__lws_seq_timeout_check(struct lws_context_per_thread *pt, lws_usec_t usnow);
+
+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 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);
+
+void
+lws_seq_destroy_all_on_pt(struct lws_context_per_thread *pt);
+
+LWS_EXTERN int
+lws_broadcast(struct lws_context_per_thread *pt, int reason, void *in, size_t len);
+
+#if defined(LWS_WITH_STATS)
+ void
+ lws_stats_bump(struct lws_context_per_thread *pt, int i, uint64_t bump);
+ void
+ lws_stats_max(struct lws_context_per_thread *pt, int index, uint64_t val);
+#else
+ static LWS_INLINE uint64_t lws_stats_bump(
+ struct lws_context_per_thread *pt, int index, uint64_t bump) {
+ (void)pt; (void)index; (void)bump; return 0; }
+ static LWS_INLINE uint64_t lws_stats_max(
+ struct lws_context_per_thread *pt, int index, uint64_t val) {
+ (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_wsi_remove_from_sul(struct lws *wsi);
+
+int
+lws_seq_pt_init(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);
+
+extern const struct lws_protocols protocol_abs_client_raw_skt,
+ protocol_abs_client_unit_test;
+
+void
+lws_inform_client_conn_fail(struct lws *wsi, void *arg, size_t len);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
+++ /dev/null
-/*
- * 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__
-
-#if !defined(_POSIX_C_SOURCE)
-#define _POSIX_C_SOURCE 200112L
-#endif
-
-#include "roles/private.h"
-
-#ifdef LWS_WITH_IPV6
-#if defined(WIN32) || defined(_WIN32)
-#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
-};
-
-enum pmd_return {
- PMDR_UNKNOWN,
- PMDR_DID_NOTHING,
- PMDR_HAS_PENDING,
- PMDR_EMPTY_NONFINAL,
- PMDR_EMPTY_FINAL,
-
- PMDR_FAILED = -1
-};
-
-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
-
-int
-__lws_sul_insert(lws_dll2_owner_t *own, lws_sorted_usec_list_t *sul,
- lws_usec_t us);
-
-lws_usec_t
-__lws_sul_check(lws_dll2_owner_t *own, lws_usec_t usnow);
-
-struct lws_timed_vh_protocol {
- struct lws_timed_vh_protocol *next;
- lws_sorted_usec_list_t sul;
- const struct lws_protocols *protocol;
- struct lws_vhost *vhost; /* only used for pending processing */
- int reason;
- int tsi_req;
-};
-
-/*
- * lws_dsh
-*/
-
-typedef struct lws_dsh_obj_head {
- lws_dll2_owner_t owner;
- int kind;
-} lws_dsh_obj_head_t;
-
-typedef struct lws_dsh lws_dsh_t;
-
-typedef struct lws_dsh_obj {
- lws_dll2_t list; /* must be first */
- lws_dsh_t *dsh; /* invalid when on free list */
- size_t size; /* invalid when on free list */
- size_t asize;
-} lws_dsh_obj_t;
-
-typedef struct lws_dsh {
- lws_dll2_t list;
- uint8_t *buf;
- lws_dsh_obj_head_t *oha; /* array of object heads/kind */
- size_t buffer_size;
- size_t locally_in_use;
- size_t locally_free;
- int count_kinds;
- uint8_t being_destroyed;
- /*
- * Overallocations at create:
- *
- * - the buffer itself
- * - the object heads array
- */
-} lws_dsh_t;
-
-/*
- * 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_dll2_owner dll_buflist_owner; /* guys with pending rxflow */
- struct lws_dll2_owner seq_owner; /* list of lws_sequencer-s */
-
- struct lws_dll2_owner pt_sul_owner;
-
-#if defined (LWS_WITH_SEQUENCER)
- lws_sorted_usec_list_t sul_seq_heartbeat;
-#endif
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- lws_sorted_usec_list_t sul_ah_lifecheck;
-#endif
-#if defined(LWS_WITH_TLS) && !defined(LWS_NO_SERVER)
- lws_sorted_usec_list_t sul_tls;
-#endif
-#if defined(LWS_PLAT_UNIX)
- lws_sorted_usec_list_t sul_plat;
-#endif
-#if defined(LWS_WITH_STATS)
- uint64_t lws_stats[LWSSTATS_SIZE];
- int updated;
- lws_sorted_usec_list_t sul_stats;
-#endif
-#if defined(LWS_WITH_PEER_LIMITS)
- lws_sorted_usec_list_t sul_peer_limits;
-#endif
-
-#if defined(LWS_WITH_TLS)
- struct lws_pt_tls tls;
-#endif
- struct lws *fake_wsi; /* used for callbacks where there's no wsi */
-
- 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_pollfd *fds;
- volatile struct lws_foreign_thread_pollfd * volatile foreign_pfd_list;
-#ifdef _WIN32
- WSAEVENT events;
- CRITICAL_SECTION interrupt_lock;
-#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;
-#ifdef _WIN32
- unsigned char interrupt_requested:1;
-#endif
-};
-
-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;
- const char *unix_socket_perms;
-
- 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_dll2_owner *same_vh_protocol_owner;
- struct lws_vhost *no_listener_vhost_list;
- struct lws_dll2_owner abstract_instances_owner;
-
-#if !defined(LWS_NO_CLIENT)
- struct lws_dll2_owner dll_cli_active_conns_owner;
-#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 */
- lws_sorted_usec_list_t sul_ping;
-#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
-
- lws_sorted_usec_list_t sul_timeout;
- lws_sorted_usec_list_t sul_hrtimer;
-
- /* 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_dll2 same_vh_protocol;
-
- lws_seq_t *seq; /* associated sequencer if any */
-
- struct lws_dll2 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_dll2 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
-
-#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
-
- /* 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_WARN_UNUSED_RESULT
-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);
-
-enum {
- LWSRXFC_ERROR = -1,
- LWSRXFC_CACHED = 0,
- LWSRXFC_ADDITIONAL = 1,
- LWSRXFC_TRIMMED = 2,
-};
-
-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 */
-int
-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 lws_usec_t
-__lws_seq_timeout_check(struct lws_context_per_thread *pt, lws_usec_t usnow);
-
-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 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);
-
-void
-lws_seq_destroy_all_on_pt(struct lws_context_per_thread *pt);
-
-LWS_EXTERN int
-lws_broadcast(struct lws_context_per_thread *pt, int reason, void *in, size_t len);
-
-#if defined(LWS_WITH_STATS)
- void
- lws_stats_bump(struct lws_context_per_thread *pt, int i, uint64_t bump);
- void
- lws_stats_max(struct lws_context_per_thread *pt, int index, uint64_t val);
-#else
- static LWS_INLINE uint64_t lws_stats_bump(
- struct lws_context_per_thread *pt, int index, uint64_t bump) {
- (void)pt; (void)index; (void)bump; return 0; }
- static LWS_INLINE uint64_t lws_stats_max(
- struct lws_context_per_thread *pt, int index, uint64_t val) {
- (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_wsi_remove_from_sul(struct lws *wsi);
-
-int
-lws_seq_pt_init(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);
-
-extern const struct lws_protocols protocol_abs_client_raw_skt,
- protocol_abs_client_unit_test;
-
-void
-lws_inform_client_conn_fail(struct lws *wsi, void *arg, size_t len);
-
-#ifdef __cplusplus
-};
-#endif
-
-#endif
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
/*
* per pending event
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
#if defined(LWS_WITH_SERVER_STATUS)
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
int
lws_callback_as_writeable(struct lws *wsi)
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
static int
sul_compare(const lws_dll2_t *d, const lws_dll2_t *i)
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
#if defined(LWS_WITH_STATS)
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
const struct lws_role_ops *available_roles[] = {
#if defined(LWS_ROLE_H2)
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
void
__lws_wsi_remove_from_sul(struct lws *wsi)
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
#if defined (_DEBUG)
void lwsi_set_role(struct lws *wsi, lws_wsi_state_t role)
-#include "core/private.h"
+#include "private-lib-core.h"
#if defined(LWS_HAVE_MALLOC_USABLE_SIZE)
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
#ifdef LWS_HAVE_SYS_TYPES_H
#include <sys/types.h>
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
#ifndef LWS_BUILD_HASH
#define LWS_BUILD_HASH "unknown-build-hash"
#endif
#if defined(LWS_WITH_ESP32)
+#if defined(LWS_AMAZON_RTOS)
+ context->last_free_heap = xPortGetFreeHeapSize();
+#else
context->last_free_heap = esp_get_free_heap_size();
+#endif
#endif
/* default to just the platform fops implementation */
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
#ifdef LWS_HAVE_SYS_TYPES_H
#include <sys/types.h>
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
#ifdef LWS_HAVE_SYS_TYPES_H
#include <sys/types.h>
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
#ifdef LWS_HAVE_SYS_TYPES_H
#include <sys/types.h>
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
#ifdef LWS_HAVE_SYS_TYPES_H
#include <sys/types.h>
--- /dev/null
+/*
+ * 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
+ */
+
+#include "lws_config.h"
+#include "lws_config_private.h"
+
+#if defined(LWS_WITH_CGI) && defined(LWS_HAVE_VFORK) && \
+ !defined(NO_GNU_SOURCE_THIS_TIME)
+ #define _GNU_SOURCE
+#endif
+
+/*
+#if !defined(_POSIX_C_SOURCE)
+#define _POSIX_C_SOURCE 200112L
+#endif
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdarg.h>
+
+#ifdef LWS_HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#include <assert.h>
+
+#ifdef LWS_HAVE_SYS_TYPES_H
+ #include <sys/types.h>
+#endif
+#if defined(LWS_HAVE_SYS_STAT_H) && !defined(LWS_PLAT_OPTEE)
+ #include <sys/stat.h>
+#endif
+
+#if LWS_MAX_SMP > 1
+ #include <pthread.h>
+#endif
+
+#ifndef LWS_DEF_HEADER_LEN
+#define LWS_DEF_HEADER_LEN 4096
+#endif
+#ifndef LWS_DEF_HEADER_POOL
+#define LWS_DEF_HEADER_POOL 4
+#endif
+#ifndef LWS_MAX_PROTOCOLS
+#define LWS_MAX_PROTOCOLS 5
+#endif
+#ifndef LWS_MAX_EXTENSIONS_ACTIVE
+#define LWS_MAX_EXTENSIONS_ACTIVE 1
+#endif
+#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
+#define AWAITING_TIMEOUT 20
+#endif
+#ifndef CIPHERS_LIST_STRING
+#define CIPHERS_LIST_STRING "DEFAULT"
+#endif
+#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"
+#endif
+
+#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 "private-lib-plat-esp32.h"
+#else
+ #if defined(WIN32) || defined(_WIN32)
+ #include "private-lib-plat-windows.h"
+ #else
+ #if defined(LWS_PLAT_OPTEE)
+ #include "private-lib-plat.h"
+ #else
+ #include "private-lib-plat-unix.h"
+ #endif
+ #endif
+#endif
+
+ /*
+ *
+ * ------ public api ------
+ *
+ */
+
+#include "libwebsockets.h"
+
+#include "private-lib-tls.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
+ #define strncasecmp _strnicmp
+ #elif !defined(__MINGW32__)
+ #define strcasecmp stricmp
+ #define strncasecmp strnicmp
+ #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
+
+
+
+#if defined(__clang__)
+#define lws_memory_barrier() __sync_synchronize()
+#elif defined(__GNUC__)
+#define lws_memory_barrier() __sync_synchronize()
+#else
+#define lws_memory_barrier()
+#endif
+
+
+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;
+
+#if defined(LWS_WITH_NETWORK)
+#include "private-lib-event-libs.h"
+
+
+struct lws_io_watcher {
+#ifdef LWS_WITH_LIBEV
+ struct lws_io_watcher_libev ev;
+#endif
+#ifdef LWS_WITH_LIBUV
+ struct lws_io_watcher_libuv uv;
+#endif
+#ifdef LWS_WITH_LIBEVENT
+ struct lws_io_watcher_libevent event;
+#endif
+ struct lws_context *context;
+
+ uint8_t actual_events;
+};
+
+struct lws_signal_watcher {
+#ifdef LWS_WITH_LIBEV
+ struct lws_signal_watcher_libev ev;
+#endif
+#ifdef LWS_WITH_LIBUV
+ struct lws_signal_watcher_libuv uv;
+#endif
+#ifdef LWS_WITH_LIBEVENT
+ struct lws_signal_watcher_libevent event;
+#endif
+ struct lws_context *context;
+};
+
+struct lws_foreign_thread_pollfd {
+ struct lws_foreign_thread_pollfd *next;
+ int fd_index;
+ int _and;
+ int _or;
+};
+#endif
+
+#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
+
+#if defined(LWS_WITH_NETWORK)
+#include "private-lib-core-net.h"
+#endif
+
+struct lws_deferred_free
+{
+ struct lws_deferred_free *next;
+ time_t deadline;
+ void *payload;
+};
+
+/*
+ * the rest is managed per-context, that includes
+ *
+ * - processwide single fd -> wsi lookup
+ * - contextwide headers pool
+ */
+
+struct lws_context {
+ time_t last_ws_ping_pong_check_s;
+ lws_usec_t time_up; /* monotonic */
+ const struct lws_plat_file_ops *fops;
+ struct lws_plat_file_ops fops_platform;
+ struct lws_context **pcontext_finalize;
+
+ const struct lws_tls_ops *tls_ops;
+
+ const char *username, *groupname;
+
+#if defined(LWS_WITH_HTTP2)
+ struct http2_settings set;
+#endif
+#if defined(LWS_WITH_ZIP_FOPS)
+ struct lws_plat_file_ops fops_zip;
+#endif
+#if defined(LWS_WITH_NETWORK)
+ struct lws_context_per_thread pt[LWS_MAX_SMP];
+ struct lws_conn_stats conn_stats;
+ struct lws_vhost *vhost_list;
+ struct lws_vhost *no_listener_vhost_list;
+ struct lws_vhost *vhost_pending_destruction_list;
+ struct lws_plugin *plugin_list;
+#ifdef _WIN32
+/* different implementation between unix and windows */
+ struct lws_fd_hashtable fd_hashtable[FD_HASHTABLE_MODULUS];
+#else
+ struct lws **lws_lookup;
+
+#endif
+#endif
+#if LWS_MAX_SMP > 1
+ struct lws_mutex_refcount mr;
+#endif
+
+#if defined(LWS_AMAZON_RTOS)
+ mbedtls_entropy_context mec;
+ mbedtls_ctr_drbg_context mcdc;
+#endif
+
+ struct lws_deferred_free *deferred_free_list;
+
+#if defined(LWS_WITH_THREADPOOL)
+ struct lws_threadpool *tp_list_head;
+#endif
+
+#if defined(LWS_WITH_PEER_LIMITS)
+ struct lws_peer **pl_hash_table;
+ struct lws_peer *peer_wait_list;
+ time_t next_cull;
+#endif
+
+ const lws_system_ops_t *system_ops;
+ 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;
+ lws_reload_func deprecation_cb;
+ void (*eventlib_signal_cb)(void *event_lib_handle, int signum);
+
+#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
+ cap_value_t caps[4];
+ char count_caps;
+#endif
+
+#if defined(LWS_WITH_NETWORK)
+#if defined(LWS_WITH_LIBEV)
+ struct lws_context_eventlibs_libev ev;
+#endif
+#if defined(LWS_WITH_LIBUV)
+ struct lws_context_eventlibs_libuv uv;
+#endif
+#if defined(LWS_WITH_LIBEVENT)
+ struct lws_context_eventlibs_libevent event;
+#endif
+ struct lws_event_loop_ops *event_loop_ops;
+#endif
+
+#if defined(LWS_WITH_TLS) && defined(LWS_WITH_NETWORK)
+ struct lws_context_tls tls;
+#endif
+
+ char canonical_hostname[128];
+ const char *server_string;
+
+#ifdef LWS_LATENCY
+ unsigned long worst_latency;
+ char worst_latency_info[256];
+#endif
+
+#if defined(LWS_WITH_ESP32)
+ unsigned long time_last_state_dump;
+ uint32_t last_free_heap;
+#endif
+
+ int max_fds;
+ int count_event_loop_static_asset_handles;
+#if !defined(LWS_NO_DAEMONIZE)
+ pid_t started_with_parent;
+#endif
+ int uid, gid;
+
+ int fd_random;
+
+ int count_wsi_allocated;
+ int count_cgi_spawned;
+ unsigned int options;
+ unsigned int fd_limit_per_thread;
+ unsigned int timeout_secs;
+ unsigned int pt_serv_buf_size;
+ int max_http_header_data;
+ int max_http_header_pool;
+ int simultaneous_ssl_restriction;
+ int simultaneous_ssl;
+#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
+ unsigned int deprecated:1;
+ unsigned int being_destroyed:1;
+ unsigned int being_destroyed1:1;
+ unsigned int being_destroyed2:1;
+ 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;
+ unsigned int max_fds_unrelated_to_ulimit:1;
+
+ short count_threads;
+ short plugin_protocol_count;
+ short plugin_extension_count;
+ short server_string_len;
+ unsigned short ws_ping_pong_interval;
+ unsigned short deprecation_pending_listen_close_count;
+
+ uint8_t max_fi;
+
+#if defined(LWS_WITH_STATS)
+ uint8_t updated;
+#endif
+};
+
+int
+lws_check_deferred_free(struct lws_context *context, int tsi, int force);
+
+#define lws_get_context_protocol(ctx, x) ctx->vhost_list->protocols[x]
+#define lws_get_vh_protocol(vh, x) vh->protocols[x]
+
+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);
+
+
+#if defined(LWS_WITH_ESP32)
+LWS_EXTERN int
+lws_find_string_in_file(const char *filename, const char *str, int stringlen);
+#endif
+
+
+signed char char_to_hex(const char c);
+
+
+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 */
+};
+
+
+LWS_EXTERN char *
+lws_strdup(const char *s);
+
+LWS_EXTERN int log_level;
+
+
+
+#ifndef LWS_LATENCY
+static LWS_INLINE void
+lws_latency(struct lws_context *context, struct lws *wsi, const char *action,
+ int ret, int completion) {
+ do {
+ (void)context; (void)wsi; (void)action; (void)ret;
+ (void)completion;
+ } while (0);
+}
+static LWS_INLINE void
+lws_latency_pre(struct lws_context *context, struct lws *wsi) {
+ do { (void)context; (void)wsi; } while (0);
+}
+#else
+#define lws_latency_pre(_context, _wsi) lws_latency(_context, _wsi, NULL, 0, 0)
+extern void
+lws_latency(struct lws_context *context, struct lws *wsi, const char *action,
+ int ret, int completion);
+#endif
+
+
+LWS_EXTERN int
+lws_b64_selftest(void);
+
+
+
+
+
+#ifndef LWS_NO_DAEMONIZE
+ LWS_EXTERN int get_daemonize_pid();
+#else
+ #define get_daemonize_pid() (0)
+#endif
+
+LWS_EXTERN void lwsl_emit_stderr(int level, const char *line);
+
+#if !defined(LWS_WITH_TLS)
+ #define LWS_SSL_ENABLED(context) (0)
+ #define lws_context_init_server_ssl(_a, _b) (0)
+ #define lws_ssl_destroy(_a)
+ #define lws_context_init_alpn(_a)
+ #define lws_ssl_capable_read lws_ssl_capable_read_no_ssl
+ #define lws_ssl_capable_write lws_ssl_capable_write_no_ssl
+ #define lws_ssl_pending lws_ssl_pending_no_ssl
+ #define lws_server_socket_service_ssl(_b, _c) (0)
+ #define lws_ssl_close(_a) (0)
+ #define lws_ssl_context_destroy(_a)
+ #define lws_ssl_SSL_CTX_destroy(_a)
+ #define lws_ssl_remove_wsi_from_buffered_list(_a)
+ #define __lws_ssl_remove_wsi_from_buffered_list(_a)
+ #define lws_context_init_ssl_library(_a)
+ #define lws_context_deinit_ssl_library(_a)
+ #define lws_tls_check_all_cert_lifetimes(_a)
+ #define lws_tls_acme_sni_cert_destroy(_a)
+#endif
+
+
+
+#if LWS_MAX_SMP > 1
+#define lws_context_lock(c, reason) lws_mutex_refcount_lock(&c->mr, reason)
+#define lws_context_unlock(c) lws_mutex_refcount_unlock(&c->mr)
+
+static LWS_INLINE void
+lws_vhost_lock(struct lws_vhost *vhost)
+{
+ pthread_mutex_lock(&vhost->lock);
+}
+
+static LWS_INLINE void
+lws_vhost_unlock(struct lws_vhost *vhost)
+{
+ pthread_mutex_unlock(&vhost->lock);
+}
+
+
+#else
+#define lws_pt_mutex_init(_a) (void)(_a)
+#define lws_pt_mutex_destroy(_a) (void)(_a)
+#define lws_pt_lock(_a, b) (void)(_a)
+#define lws_pt_unlock(_a) (void)(_a)
+#define lws_context_lock(_a, _b) (void)(_a)
+#define lws_context_unlock(_a) (void)(_a)
+#define lws_vhost_lock(_a) (void)(_a)
+#define lws_vhost_unlock(_a) (void)(_a)
+#define lws_pt_stats_lock(_a) (void)(_a)
+#define lws_pt_stats_unlock(_a) (void)(_a)
+#endif
+
+LWS_EXTERN int LWS_WARN_UNUSED_RESULT
+lws_ssl_capable_read_no_ssl(struct lws *wsi, unsigned char *buf, int len);
+
+LWS_EXTERN int LWS_WARN_UNUSED_RESULT
+lws_ssl_capable_write_no_ssl(struct lws *wsi, unsigned char *buf, int len);
+
+LWS_EXTERN int LWS_WARN_UNUSED_RESULT
+lws_ssl_pending_no_ssl(struct lws *wsi);
+
+int
+lws_tls_check_cert_lifetime(struct lws_vhost *vhost);
+
+int lws_jws_selftest(void);
+int lws_jwe_selftest(void);
+
+int
+lws_protocol_init(struct lws_context *context);
+
+int
+lws_bind_protocol(struct lws *wsi, const struct lws_protocols *p,
+ const char *reason);
+
+const struct lws_protocol_vhost_options *
+lws_vhost_protocol_options(struct lws_vhost *vh, const char *name);
+
+const struct lws_http_mount *
+lws_find_mount(struct lws *wsi, const char *uri_ptr, int uri_len);
+
+/*
+ * custom allocator
+ */
+LWS_EXTERN void *
+lws_realloc(void *ptr, size_t size, const char *reason);
+
+LWS_EXTERN void * LWS_WARN_UNUSED_RESULT
+lws_zalloc(size_t size, const char *reason);
+
+#ifdef LWS_PLAT_OPTEE
+void *lws_malloc(size_t size, const char *reason);
+void lws_free(void *p);
+#define lws_free_set_NULL(P) do { lws_free(P); (P) = NULL; } while(0)
+#else
+#define lws_malloc(S, R) lws_realloc(NULL, S, R)
+#define lws_free(P) lws_realloc(P, 0, "lws_free")
+#define lws_free_set_NULL(P) do { lws_realloc(P, 0, "free"); (P) = NULL; } while(0)
+#endif
+
+int
+lws_create_event_pipes(struct lws_context *context);
+
+int
+lws_plat_apply_FD_CLOEXEC(int n);
+
+const struct lws_plat_file_ops *
+lws_vfs_select_fops(const struct lws_plat_file_ops *fops, const char *vfs_path,
+ const char **vpath);
+
+/* lws_plat_ */
+
+LWS_EXTERN int
+lws_plat_context_early_init(void);
+LWS_EXTERN void
+lws_plat_context_early_destroy(struct lws_context *context);
+LWS_EXTERN void
+lws_plat_context_late_destroy(struct lws_context *context);
+
+LWS_EXTERN int
+lws_plat_init(struct lws_context *context,
+ const struct lws_context_creation_info *info);
+LWS_EXTERN int
+lws_plat_drop_app_privileges(struct lws_context *context, int actually_drop);
+
+#if defined(LWS_WITH_UNIX_SOCK)
+int
+lws_plat_user_colon_group_to_ids(const char *u_colon_g, uid_t *puid, gid_t *pgid);
+#endif
+
+LWS_EXTERN int
+lws_check_byte_utf8(unsigned char state, unsigned char c);
+LWS_EXTERN int LWS_WARN_UNUSED_RESULT
+lws_check_utf8(unsigned char *state, unsigned char *buf, size_t len);
+LWS_EXTERN int alloc_file(struct lws_context *context, const char *filename,
+ uint8_t **buf, lws_filepos_t *amount);
+
+void
+lws_context_destroy2(struct lws_context *context);
+
+
+#ifdef __cplusplus
+};
+#endif
+++ /dev/null
-/*
- * 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
- */
-
-#include "lws_config.h"
-#include "lws_config_private.h"
-
-#if defined(LWS_WITH_CGI) && defined(LWS_HAVE_VFORK) && \
- !defined(NO_GNU_SOURCE_THIS_TIME)
- #define _GNU_SOURCE
-#endif
-
-/*
-#if !defined(_POSIX_C_SOURCE)
-#define _POSIX_C_SOURCE 200112L
-#endif
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <ctype.h>
-#include <limits.h>
-#include <stdarg.h>
-
-#ifdef LWS_HAVE_INTTYPES_H
-#include <inttypes.h>
-#endif
-
-#include <assert.h>
-
-#ifdef LWS_HAVE_SYS_TYPES_H
- #include <sys/types.h>
-#endif
-#if defined(LWS_HAVE_SYS_STAT_H) && !defined(LWS_PLAT_OPTEE)
- #include <sys/stat.h>
-#endif
-
-#if LWS_MAX_SMP > 1
- #include <pthread.h>
-#endif
-
-#ifndef LWS_DEF_HEADER_LEN
-#define LWS_DEF_HEADER_LEN 4096
-#endif
-#ifndef LWS_DEF_HEADER_POOL
-#define LWS_DEF_HEADER_POOL 4
-#endif
-#ifndef LWS_MAX_PROTOCOLS
-#define LWS_MAX_PROTOCOLS 5
-#endif
-#ifndef LWS_MAX_EXTENSIONS_ACTIVE
-#define LWS_MAX_EXTENSIONS_ACTIVE 1
-#endif
-#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
-#define AWAITING_TIMEOUT 20
-#endif
-#ifndef CIPHERS_LIST_STRING
-#define CIPHERS_LIST_STRING "DEFAULT"
-#endif
-#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"
-#endif
-
-#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
-
- /*
- *
- * ------ 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
- #define strncasecmp _strnicmp
- #elif !defined(__MINGW32__)
- #define strcasecmp stricmp
- #define strncasecmp strnicmp
- #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
-
-
-
-#if defined(__clang__)
-#define lws_memory_barrier() __sync_synchronize()
-#elif defined(__GNUC__)
-#define lws_memory_barrier() __sync_synchronize()
-#else
-#define lws_memory_barrier()
-#endif
-
-
-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;
-
-#if defined(LWS_WITH_NETWORK)
-#include "event-libs/private.h"
-
-
-struct lws_io_watcher {
-#ifdef LWS_WITH_LIBEV
- struct lws_io_watcher_libev ev;
-#endif
-#ifdef LWS_WITH_LIBUV
- struct lws_io_watcher_libuv uv;
-#endif
-#ifdef LWS_WITH_LIBEVENT
- struct lws_io_watcher_libevent event;
-#endif
- struct lws_context *context;
-
- uint8_t actual_events;
-};
-
-struct lws_signal_watcher {
-#ifdef LWS_WITH_LIBEV
- struct lws_signal_watcher_libev ev;
-#endif
-#ifdef LWS_WITH_LIBUV
- struct lws_signal_watcher_libuv uv;
-#endif
-#ifdef LWS_WITH_LIBEVENT
- struct lws_signal_watcher_libevent event;
-#endif
- struct lws_context *context;
-};
-
-struct lws_foreign_thread_pollfd {
- struct lws_foreign_thread_pollfd *next;
- int fd_index;
- int _and;
- int _or;
-};
-#endif
-
-#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
-
-#if defined(LWS_WITH_NETWORK)
-#include "core-net/private.h"
-#endif
-
-struct lws_deferred_free
-{
- struct lws_deferred_free *next;
- time_t deadline;
- void *payload;
-};
-
-/*
- * the rest is managed per-context, that includes
- *
- * - processwide single fd -> wsi lookup
- * - contextwide headers pool
- */
-
-struct lws_context {
- time_t last_ws_ping_pong_check_s;
- lws_usec_t time_up; /* monotonic */
- const struct lws_plat_file_ops *fops;
- struct lws_plat_file_ops fops_platform;
- struct lws_context **pcontext_finalize;
-
- const struct lws_tls_ops *tls_ops;
-
- const char *username, *groupname;
-
-#if defined(LWS_WITH_HTTP2)
- struct http2_settings set;
-#endif
-#if defined(LWS_WITH_ZIP_FOPS)
- struct lws_plat_file_ops fops_zip;
-#endif
-#if defined(LWS_WITH_NETWORK)
- struct lws_context_per_thread pt[LWS_MAX_SMP];
- struct lws_conn_stats conn_stats;
- struct lws_vhost *vhost_list;
- struct lws_vhost *no_listener_vhost_list;
- struct lws_vhost *vhost_pending_destruction_list;
- struct lws_plugin *plugin_list;
-#ifdef _WIN32
-/* different implementation between unix and windows */
- struct lws_fd_hashtable fd_hashtable[FD_HASHTABLE_MODULUS];
-#else
- struct lws **lws_lookup;
-
-#endif
-#endif
-#if LWS_MAX_SMP > 1
- struct lws_mutex_refcount mr;
-#endif
-
-#if defined(LWS_AMAZON_RTOS)
- mbedtls_entropy_context mec;
- mbedtls_ctr_drbg_context mcdc;
-#endif
-
- struct lws_deferred_free *deferred_free_list;
-
-#if defined(LWS_WITH_THREADPOOL)
- struct lws_threadpool *tp_list_head;
-#endif
-
-#if defined(LWS_WITH_PEER_LIMITS)
- struct lws_peer **pl_hash_table;
- struct lws_peer *peer_wait_list;
- time_t next_cull;
-#endif
-
- const lws_system_ops_t *system_ops;
- 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;
- lws_reload_func deprecation_cb;
- void (*eventlib_signal_cb)(void *event_lib_handle, int signum);
-
-#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
- cap_value_t caps[4];
- char count_caps;
-#endif
-
-#if defined(LWS_WITH_NETWORK)
-#if defined(LWS_WITH_LIBEV)
- struct lws_context_eventlibs_libev ev;
-#endif
-#if defined(LWS_WITH_LIBUV)
- struct lws_context_eventlibs_libuv uv;
-#endif
-#if defined(LWS_WITH_LIBEVENT)
- struct lws_context_eventlibs_libevent event;
-#endif
- struct lws_event_loop_ops *event_loop_ops;
-#endif
-
-#if defined(LWS_WITH_TLS) && defined(LWS_WITH_NETWORK)
- struct lws_context_tls tls;
-#endif
-
- char canonical_hostname[128];
- const char *server_string;
-
-#ifdef LWS_LATENCY
- unsigned long worst_latency;
- char worst_latency_info[256];
-#endif
-
-#if defined(LWS_WITH_ESP32)
- unsigned long time_last_state_dump;
- uint32_t last_free_heap;
-#endif
-
- int max_fds;
- int count_event_loop_static_asset_handles;
-#if !defined(LWS_NO_DAEMONIZE)
- pid_t started_with_parent;
-#endif
- int uid, gid;
-
- int fd_random;
-
- int count_wsi_allocated;
- int count_cgi_spawned;
- unsigned int options;
- unsigned int fd_limit_per_thread;
- unsigned int timeout_secs;
- unsigned int pt_serv_buf_size;
- int max_http_header_data;
- int max_http_header_pool;
- int simultaneous_ssl_restriction;
- int simultaneous_ssl;
-#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
- unsigned int deprecated:1;
- unsigned int being_destroyed:1;
- unsigned int being_destroyed1:1;
- unsigned int being_destroyed2:1;
- 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;
- unsigned int max_fds_unrelated_to_ulimit:1;
-
- short count_threads;
- short plugin_protocol_count;
- short plugin_extension_count;
- short server_string_len;
- unsigned short ws_ping_pong_interval;
- unsigned short deprecation_pending_listen_close_count;
-
- uint8_t max_fi;
-
-#if defined(LWS_WITH_STATS)
- uint8_t updated;
-#endif
-};
-
-int
-lws_check_deferred_free(struct lws_context *context, int tsi, int force);
-
-#define lws_get_context_protocol(ctx, x) ctx->vhost_list->protocols[x]
-#define lws_get_vh_protocol(vh, x) vh->protocols[x]
-
-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);
-
-
-#if defined(LWS_WITH_ESP32)
-LWS_EXTERN int
-lws_find_string_in_file(const char *filename, const char *str, int stringlen);
-#endif
-
-
-signed char char_to_hex(const char c);
-
-
-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 */
-};
-
-
-LWS_EXTERN char *
-lws_strdup(const char *s);
-
-LWS_EXTERN int log_level;
-
-
-
-#ifndef LWS_LATENCY
-static LWS_INLINE void
-lws_latency(struct lws_context *context, struct lws *wsi, const char *action,
- int ret, int completion) {
- do {
- (void)context; (void)wsi; (void)action; (void)ret;
- (void)completion;
- } while (0);
-}
-static LWS_INLINE void
-lws_latency_pre(struct lws_context *context, struct lws *wsi) {
- do { (void)context; (void)wsi; } while (0);
-}
-#else
-#define lws_latency_pre(_context, _wsi) lws_latency(_context, _wsi, NULL, 0, 0)
-extern void
-lws_latency(struct lws_context *context, struct lws *wsi, const char *action,
- int ret, int completion);
-#endif
-
-
-LWS_EXTERN int
-lws_b64_selftest(void);
-
-
-
-
-
-#ifndef LWS_NO_DAEMONIZE
- LWS_EXTERN int get_daemonize_pid();
-#else
- #define get_daemonize_pid() (0)
-#endif
-
-LWS_EXTERN void lwsl_emit_stderr(int level, const char *line);
-
-#if !defined(LWS_WITH_TLS)
- #define LWS_SSL_ENABLED(context) (0)
- #define lws_context_init_server_ssl(_a, _b) (0)
- #define lws_ssl_destroy(_a)
- #define lws_context_init_alpn(_a)
- #define lws_ssl_capable_read lws_ssl_capable_read_no_ssl
- #define lws_ssl_capable_write lws_ssl_capable_write_no_ssl
- #define lws_ssl_pending lws_ssl_pending_no_ssl
- #define lws_server_socket_service_ssl(_b, _c) (0)
- #define lws_ssl_close(_a) (0)
- #define lws_ssl_context_destroy(_a)
- #define lws_ssl_SSL_CTX_destroy(_a)
- #define lws_ssl_remove_wsi_from_buffered_list(_a)
- #define __lws_ssl_remove_wsi_from_buffered_list(_a)
- #define lws_context_init_ssl_library(_a)
- #define lws_context_deinit_ssl_library(_a)
- #define lws_tls_check_all_cert_lifetimes(_a)
- #define lws_tls_acme_sni_cert_destroy(_a)
-#endif
-
-
-
-#if LWS_MAX_SMP > 1
-#define lws_context_lock(c, reason) lws_mutex_refcount_lock(&c->mr, reason)
-#define lws_context_unlock(c) lws_mutex_refcount_unlock(&c->mr)
-
-static LWS_INLINE void
-lws_vhost_lock(struct lws_vhost *vhost)
-{
- pthread_mutex_lock(&vhost->lock);
-}
-
-static LWS_INLINE void
-lws_vhost_unlock(struct lws_vhost *vhost)
-{
- pthread_mutex_unlock(&vhost->lock);
-}
-
-
-#else
-#define lws_pt_mutex_init(_a) (void)(_a)
-#define lws_pt_mutex_destroy(_a) (void)(_a)
-#define lws_pt_lock(_a, b) (void)(_a)
-#define lws_pt_unlock(_a) (void)(_a)
-#define lws_context_lock(_a, _b) (void)(_a)
-#define lws_context_unlock(_a) (void)(_a)
-#define lws_vhost_lock(_a) (void)(_a)
-#define lws_vhost_unlock(_a) (void)(_a)
-#define lws_pt_stats_lock(_a) (void)(_a)
-#define lws_pt_stats_unlock(_a) (void)(_a)
-#endif
-
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_ssl_capable_read_no_ssl(struct lws *wsi, unsigned char *buf, int len);
-
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_ssl_capable_write_no_ssl(struct lws *wsi, unsigned char *buf, int len);
-
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_ssl_pending_no_ssl(struct lws *wsi);
-
-int
-lws_tls_check_cert_lifetime(struct lws_vhost *vhost);
-
-int lws_jws_selftest(void);
-int lws_jwe_selftest(void);
-
-int
-lws_protocol_init(struct lws_context *context);
-
-int
-lws_bind_protocol(struct lws *wsi, const struct lws_protocols *p,
- const char *reason);
-
-const struct lws_protocol_vhost_options *
-lws_vhost_protocol_options(struct lws_vhost *vh, const char *name);
-
-const struct lws_http_mount *
-lws_find_mount(struct lws *wsi, const char *uri_ptr, int uri_len);
-
-/*
- * custom allocator
- */
-LWS_EXTERN void *
-lws_realloc(void *ptr, size_t size, const char *reason);
-
-LWS_EXTERN void * LWS_WARN_UNUSED_RESULT
-lws_zalloc(size_t size, const char *reason);
-
-#ifdef LWS_PLAT_OPTEE
-void *lws_malloc(size_t size, const char *reason);
-void lws_free(void *p);
-#define lws_free_set_NULL(P) do { lws_free(P); (P) = NULL; } while(0)
-#else
-#define lws_malloc(S, R) lws_realloc(NULL, S, R)
-#define lws_free(P) lws_realloc(P, 0, "lws_free")
-#define lws_free_set_NULL(P) do { lws_realloc(P, 0, "free"); (P) = NULL; } while(0)
-#endif
-
-int
-lws_create_event_pipes(struct lws_context *context);
-
-int
-lws_plat_apply_FD_CLOEXEC(int n);
-
-const struct lws_plat_file_ops *
-lws_vfs_select_fops(const struct lws_plat_file_ops *fops, const char *vfs_path,
- const char **vpath);
-
-/* lws_plat_ */
-
-LWS_EXTERN int
-lws_plat_context_early_init(void);
-LWS_EXTERN void
-lws_plat_context_early_destroy(struct lws_context *context);
-LWS_EXTERN void
-lws_plat_context_late_destroy(struct lws_context *context);
-
-LWS_EXTERN int
-lws_plat_init(struct lws_context *context,
- const struct lws_context_creation_info *info);
-LWS_EXTERN int
-lws_plat_drop_app_privileges(struct lws_context *context, int actually_drop);
-
-#if defined(LWS_WITH_UNIX_SOCK)
-int
-lws_plat_user_colon_group_to_ids(const char *u_colon_g, uid_t *puid, gid_t *pgid);
-#endif
-
-LWS_EXTERN int
-lws_check_byte_utf8(unsigned char state, unsigned char c);
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_check_utf8(unsigned char *state, unsigned char *buf, size_t len);
-LWS_EXTERN int alloc_file(struct lws_context *context, const char *filename,
- uint8_t **buf, lws_filepos_t *amount);
-
-void
-lws_context_destroy2(struct lws_context *context);
-
-
-#ifdef __cplusplus
-};
-#endif
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
LWS_VISIBLE LWS_EXTERN void
### Event loop ops struct
-The event lib support is defined by `struct lws_event_loop_ops` in `lib/event-libs/private.h`,
+The event lib support is defined by `struct lws_event_loop_ops` in `lib/event-libs/private-lib-event-libs.h`,
each event lib support instantiates one of these and fills in the appropriate ops
callbacks to perform its job. By convention that lives in
`./lib/event-libs/**lib name**/**lib_name**.c`.
Truly private declarations for the event lib can go in the event-libs directory as you like.
However when the declarations must be accessible to other things in lws build, eg,
the event lib support adds members to `struct lws` when enabled, they should be in the
-event lib supporr directory in a file `private.h`.
+event lib support directory in a file `private-lib-event-libs-myeventlib.h`.
-Search for "bring in event libs private declarations" in `./lib/core/private.h
+Search for "bring in event libs private declarations" in `./lib/core/private-lib-core.h
and add your private event lib support file there following the style used for the other
event libs, eg,
```
#if defined(LWS_WITH_LIBUV)
- #include "event-libs/libuv/private.h"
+ #include "event-libs/libuv/private-lib-event-libs-libuv.h"
#endif
```
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
static void
lws_ev_hrtimer_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents)
--- /dev/null
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010 - 2018 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
+ *
+ * This is included from core/private.h if LWS_WITH_LIBEV
+ */
+
+#include <ev.h>
+
+#define LWS_EV_REFCOUNT_STATIC_HANDLE_NEW(_x, _ctx) \
+ { (_x)->data = _ctx; \
+ _ctx->count_event_loop_static_asset_handles++; }
+#define LWS_EV_REFCOUNT_STATIC_HANDLE_TO_CONTEXT(_x) \
+ ((struct lws_context *)(_x)->data)))
+#define LWS_EV_REFCOUNT_STATIC_HANDLE_DESTROYED(_x) \
+ (--(LWS_UV_REFCOUNT_STATIC_HANDLE_TO_CONTEXT(_x)-> \
+ count_event_loop_static_asset_handles))
+
+struct lws_pt_eventlibs_libev {
+ struct ev_loop *io_loop;
+ struct ev_timer hrtimer;
+ struct ev_idle idle;
+};
+
+struct lws_io_watcher_libev {
+ ev_io watcher;
+};
+
+struct lws_signal_watcher_libev {
+ ev_signal watcher;
+};
+
+struct lws_context_eventlibs_libev {
+ int placeholder;
+};
+
+extern struct lws_event_loop_ops event_loop_ops_ev;
+++ /dev/null
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 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
- *
- * This is included from core/private.h if LWS_WITH_LIBEV
- */
-
-#include <ev.h>
-
-#define LWS_EV_REFCOUNT_STATIC_HANDLE_NEW(_x, _ctx) \
- { (_x)->data = _ctx; \
- _ctx->count_event_loop_static_asset_handles++; }
-#define LWS_EV_REFCOUNT_STATIC_HANDLE_TO_CONTEXT(_x) \
- ((struct lws_context *)(_x)->data)))
-#define LWS_EV_REFCOUNT_STATIC_HANDLE_DESTROYED(_x) \
- (--(LWS_UV_REFCOUNT_STATIC_HANDLE_TO_CONTEXT(_x)-> \
- count_event_loop_static_asset_handles))
-
-struct lws_pt_eventlibs_libev {
- struct ev_loop *io_loop;
- struct ev_timer hrtimer;
- struct ev_idle idle;
-};
-
-struct lws_io_watcher_libev {
- ev_io watcher;
-};
-
-struct lws_signal_watcher_libev {
- ev_signal watcher;
-};
-
-struct lws_context_eventlibs_libev {
- int placeholder;
-};
-
-extern struct lws_event_loop_ops event_loop_ops_ev;
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
static void
lws_event_hrtimer_cb(int fd, short event, void *p)
--- /dev/null
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010 - 2018 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
+ *
+ * This is included from core/private.h if LWS_WITH_LIBEVENT
+ */
+
+#include <event2/event.h>
+
+struct lws_pt_eventlibs_libevent {
+ struct event_base *io_loop;
+ struct event *hrtimer;
+ struct event *idle_timer;
+};
+
+struct lws_io_watcher_libevent {
+ struct event *watcher;
+};
+
+struct lws_signal_watcher_libevent {
+ struct event *watcher;
+};
+
+struct lws_context_eventlibs_libevent {
+ int placeholder;
+};
+
+extern struct lws_event_loop_ops event_loop_ops_event;
+++ /dev/null
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 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
- *
- * This is included from core/private.h if LWS_WITH_LIBEVENT
- */
-
-#include <event2/event.h>
-
-struct lws_pt_eventlibs_libevent {
- struct event_base *io_loop;
- struct event *hrtimer;
- struct event *idle_timer;
-};
-
-struct lws_io_watcher_libevent {
- struct event *watcher;
-};
-
-struct lws_signal_watcher_libevent {
- struct event *watcher;
-};
-
-struct lws_context_eventlibs_libevent {
- int placeholder;
-};
-
-extern struct lws_event_loop_ops event_loop_ops_event;
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
static void
lws_uv_sultimer_cb(uv_timer_t *timer
--- /dev/null
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010 - 2018 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
+ *
+ * This is included from core/private.h if LWS_WITH_LIBUV
+ */
+
+#include <uv.h>
+
+/*
+ * libuv's async destroy cb means that asking to close something doesn't mean
+ * you can destroy it or parent things until after the close completes.
+ *
+ * So we must reference-count creation and close completions with libuv.
+ *
+ * All "static" (per-pt or per-context) uv handles must
+ *
+ * - have their .data set to point to the context
+ *
+ * - contribute to context->uv_count_static_asset_handles
+ * counting
+ */
+#define LWS_UV_REFCOUNT_STATIC_HANDLE_NEW(_x, _ctx) \
+ { uv_handle_t *_uht = (uv_handle_t *)(_x); _uht->data = _ctx; \
+ _ctx->count_event_loop_static_asset_handles++; }
+#define LWS_UV_REFCOUNT_STATIC_HANDLE_TO_CONTEXT(_x) \
+ ((struct lws_context *)((uv_handle_t *)((_x)->data)))
+#define LWS_UV_REFCOUNT_STATIC_HANDLE_DESTROYED(_x) \
+ (--(LWS_UV_REFCOUNT_STATIC_HANDLE_TO_CONTEXT(_x)-> \
+ count_event_loop_static_asset_handles))
+
+struct lws_pt_eventlibs_libuv {
+ uv_loop_t *io_loop;
+ uv_signal_t signals[8];
+ uv_timer_t sultimer;
+ uv_idle_t idle;
+};
+
+struct lws_context_eventlibs_libuv {
+ uv_loop_t loop;
+};
+
+struct lws_io_watcher_libuv {
+ uv_poll_t *pwatcher;
+};
+
+struct lws_signal_watcher_libuv {
+ uv_signal_t watcher;
+};
+
+extern struct lws_event_loop_ops event_loop_ops_uv;
+
+uv_loop_t *
+lws_uv_getloop(struct lws_context *context, int tsi);
+
+int
+lws_uv_plugins_init(struct lws_context *context, const char * const *d);
+
+int
+lws_uv_plugins_destroy(struct lws_context *context);
+++ /dev/null
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 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
- *
- * This is included from core/private.h if LWS_WITH_LIBUV
- */
-
-#include <uv.h>
-
-/*
- * libuv's async destroy cb means that asking to close something doesn't mean
- * you can destroy it or parent things until after the close completes.
- *
- * So we must reference-count creation and close completions with libuv.
- *
- * All "static" (per-pt or per-context) uv handles must
- *
- * - have their .data set to point to the context
- *
- * - contribute to context->uv_count_static_asset_handles
- * counting
- */
-#define LWS_UV_REFCOUNT_STATIC_HANDLE_NEW(_x, _ctx) \
- { uv_handle_t *_uht = (uv_handle_t *)(_x); _uht->data = _ctx; \
- _ctx->count_event_loop_static_asset_handles++; }
-#define LWS_UV_REFCOUNT_STATIC_HANDLE_TO_CONTEXT(_x) \
- ((struct lws_context *)((uv_handle_t *)((_x)->data)))
-#define LWS_UV_REFCOUNT_STATIC_HANDLE_DESTROYED(_x) \
- (--(LWS_UV_REFCOUNT_STATIC_HANDLE_TO_CONTEXT(_x)-> \
- count_event_loop_static_asset_handles))
-
-struct lws_pt_eventlibs_libuv {
- uv_loop_t *io_loop;
- uv_signal_t signals[8];
- uv_timer_t sultimer;
- uv_idle_t idle;
-};
-
-struct lws_context_eventlibs_libuv {
- uv_loop_t loop;
-};
-
-struct lws_io_watcher_libuv {
- uv_poll_t *pwatcher;
-};
-
-struct lws_signal_watcher_libuv {
- uv_signal_t watcher;
-};
-
-extern struct lws_event_loop_ops event_loop_ops_uv;
-
-uv_loop_t *
-lws_uv_getloop(struct lws_context *context, int tsi);
-
-int
-lws_uv_plugins_init(struct lws_context *context, const char * const *d);
-
-int
-lws_uv_plugins_destroy(struct lws_context *context);
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*
- * This is included from core/private.h if LWS_ROLE_WS
+ * This is included from private-lib-core.h if LWS_ROLE_WS
*/
-#include <core/private.h>
+#include <private-lib-core.h>
struct lws_event_loop_ops event_loop_ops_poll = {
/* name */ "poll",
--- /dev/null
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010 - 2018 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
+ *
+ */
+
+extern struct lws_event_loop_ops event_loop_ops_poll;
+++ /dev/null
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 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
- *
- */
-
-extern struct lws_event_loop_ops event_loop_ops_poll;
--- /dev/null
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010 - 2018 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
+ *
+ * This is included from private-lib-core.h
+ */
+
+struct lws_event_loop_ops {
+ const char *name;
+ /* event loop-specific context init during context creation */
+ int (*init_context)(struct lws_context *context,
+ const struct lws_context_creation_info *info);
+ /* called during lws_destroy_context */
+ int (*destroy_context1)(struct lws_context *context);
+ /* called during lws_destroy_context2 */
+ int (*destroy_context2)(struct lws_context *context);
+ /* init vhost listening wsi */
+ int (*init_vhost_listen_wsi)(struct lws *wsi);
+ /* init the event loop for a pt */
+ int (*init_pt)(struct lws_context *context, void *_loop, int tsi);
+ /* called at end of first phase of close_free_wsi() */
+ int (*wsi_logical_close)(struct lws *wsi);
+ /* return nonzero if client connect not allowed */
+ int (*check_client_connect_ok)(struct lws *wsi);
+ /* close handle manually */
+ void (*close_handle_manually)(struct lws *wsi);
+ /* event loop accept processing */
+ int (*accept)(struct lws *wsi);
+ /* control wsi active events */
+ void (*io)(struct lws *wsi, int flags);
+ /* run the event loop for a pt */
+ void (*run_pt)(struct lws_context *context, int tsi);
+ /* called before pt is destroyed */
+ void (*destroy_pt)(struct lws_context *context, int tsi);
+ /* called just before wsi is freed */
+ void (*destroy_wsi)(struct lws *wsi);
+
+ unsigned int periodic_events_available:1;
+};
+
+/* bring in event libs private declarations */
+
+#if defined(LWS_WITH_POLL)
+#include "private-lib-event-libs-poll.h"
+#endif
+
+#if defined(LWS_WITH_LIBUV)
+#include "private-lib-event-libs-libuv.h"
+#endif
+
+#if defined(LWS_WITH_LIBEVENT)
+#include "private-lib-event-libs-libevent.h"
+#endif
+
+#if defined(LWS_WITH_LIBEV)
+#include "private-lib-event-libs-libev.h"
+#endif
+
+++ /dev/null
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 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
- *
- * This is included from core/private.h
- */
-
-struct lws_event_loop_ops {
- const char *name;
- /* event loop-specific context init during context creation */
- int (*init_context)(struct lws_context *context,
- const struct lws_context_creation_info *info);
- /* called during lws_destroy_context */
- int (*destroy_context1)(struct lws_context *context);
- /* called during lws_destroy_context2 */
- int (*destroy_context2)(struct lws_context *context);
- /* init vhost listening wsi */
- int (*init_vhost_listen_wsi)(struct lws *wsi);
- /* init the event loop for a pt */
- int (*init_pt)(struct lws_context *context, void *_loop, int tsi);
- /* called at end of first phase of close_free_wsi() */
- int (*wsi_logical_close)(struct lws *wsi);
- /* return nonzero if client connect not allowed */
- int (*check_client_connect_ok)(struct lws *wsi);
- /* close handle manually */
- void (*close_handle_manually)(struct lws *wsi);
- /* event loop accept processing */
- int (*accept)(struct lws *wsi);
- /* control wsi active events */
- void (*io)(struct lws *wsi, int flags);
- /* run the event loop for a pt */
- void (*run_pt)(struct lws_context *context, int tsi);
- /* called before pt is destroyed */
- void (*destroy_pt)(struct lws_context *context, int tsi);
- /* called just before wsi is freed */
- void (*destroy_wsi)(struct lws *wsi);
-
- unsigned int periodic_events_available:1;
-};
-
-/* bring in event libs private declarations */
-
-#if defined(LWS_WITH_POLL)
-#include "event-libs/poll/private.h"
-#endif
-
-#if defined(LWS_WITH_LIBUV)
-#include "event-libs/libuv/private.h"
-#endif
-
-#if defined(LWS_WITH_LIBEVENT)
-#include "event-libs/libevent/private.h"
-#endif
-
-#if defined(LWS_WITH_LIBEV)
-#include "event-libs/libev/private.h"
-#endif
-
* JWE code for payload encrypt / decrypt using aescbc
*
*/
-#include "core/private.h"
-#include "jose/jwe/private.h"
+
+#include "private-lib-core.h"
+#include "private-lib-jose-jwe.h"
int
lws_jwe_encrypt_cbc_hs(struct lws_jwe *jwe, uint8_t *cek,
* JWE code related to aes gcm
*
*/
-#include "core/private.h"
-#include "jose/jwe/private.h"
+
+#include "private-lib-core.h"
+#include "private-lib-jose-jwe.h"
/*
* NOTICE this is AESGCM content encryption, it's not AES GCM key wrapping
* JWE code related to aeskw cbc
*
*/
-#include "core/private.h"
-#include "jose/jwe/private.h"
+#include "private-lib-core.h"
+#include "private-lib-jose-jwe.h"
/*
* RFC3394 Key Wrap uses a 128-bit key, and bloats what it is wrapping by
* JWE code related to ecdh-es + Concat KDF and aes kw
*
*/
-#include "core/private.h"
-#include "jose/jwe/private.h"
+
+#include "private-lib-core.h"
+#include "private-lib-jose-jwe.h"
/*
* From RFC7518 JWA
* JWE code related to rsa + aescbc
*
*/
-#include "core/private.h"
-#include "jose/jwe/private.h"
+
+#include "private-lib-core.h"
+#include "private-lib-jose-jwe.h"
/*
* Requirements on entry:
* JWE code related to aes gcm
*
*/
-#include "core/private.h"
-#include "jose/jwe/private.h"
+
+#include "private-lib-core.h"
+#include "private-lib-jose-jwe.h"
#define LWS_AESGCM_IV 12
* This supports RFC7516 JSON Web Encryption
*
*/
-#include "core/private.h"
-#include "jose/private.h"
-#include "jose/jwe/private.h"
+
+#include "private-lib-core.h"
+#include "private-lib-jose.h"
+#include "private-lib-jose-jwe.h"
/*
* Currently only support flattened or compact (implicitly single signature)
--- /dev/null
+/*
+ * libwebsockets - JSON Web Encryption support
+ *
+ * Copyright (C) 2018 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
+ *
+ */
+#define LWS_AESGCM_IV 12
+#define LWS_AESGCM_TAG 16
+
+/* jwe-rsa-aescbc.c */
+
+int
+lws_jwe_auth_and_decrypt_rsa_aes_cbc_hs(struct lws_jwe *jwe);
+
+
+int
+lws_jwe_encrypt_rsa_aes_cbc_hs(struct lws_jwe *jwe,
+ char *temp, int *temp_len);
+
+int
+lws_jwe_auth_and_decrypt_cbc_hs(struct lws_jwe *jwe, uint8_t *enc_cek,
+ uint8_t *aad, int aad_len);
+
+
+/* jws-rsa-aesgcm.c */
+
+int
+lws_jwe_auth_and_decrypt_gcm(struct lws_jwe *jwe, uint8_t *enc_cek,
+ uint8_t *aad, int aad_len);
+
+int
+lws_jwe_auth_and_decrypt_rsa_aes_gcm(struct lws_jwe *jwe);
+
+int
+lws_jwe_encrypt_gcm(struct lws_jwe *jwe,
+ uint8_t *enc_cek, uint8_t *aad, int aad_len);
+
+int
+lws_jwe_encrypt_rsa_aes_gcm(struct lws_jwe *jwe,
+ char *temp, int *temp_len);
+
+
+
+
+/* jwe-rsa-aeskw.c */
+
+int
+lws_jwe_encrypt_aeskw_cbc_hs(struct lws_jwe *jwe,
+ char *temp, int *temp_len);
+
+int
+lws_jwe_auth_and_decrypt_aeskw_cbc_hs(struct lws_jwe *jwe);
+
+/* aescbc.c */
+
+int
+lws_jwe_auth_and_decrypt_cbc_hs(struct lws_jwe *jwe, uint8_t *enc_cek,
+ uint8_t *aad, int aad_len);
+
+int
+lws_jwe_encrypt_cbc_hs(struct lws_jwe *jwe,
+ uint8_t *cek, uint8_t *aad, int aad_len);
+
+int
+lws_jwe_auth_and_decrypt_ecdh_cbc_hs(struct lws_jwe *jwe,
+ char *temp, int *temp_len);
+
+int
+lws_jwe_encrypt_ecdh_cbc_hs(struct lws_jwe *jwe,
+ char *temp, int *temp_len);
+++ /dev/null
-/*
- * libwebsockets - JSON Web Encryption support
- *
- * Copyright (C) 2018 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
- *
- */
-#define LWS_AESGCM_IV 12
-#define LWS_AESGCM_TAG 16
-
-/* jwe-rsa-aescbc.c */
-
-int
-lws_jwe_auth_and_decrypt_rsa_aes_cbc_hs(struct lws_jwe *jwe);
-
-
-int
-lws_jwe_encrypt_rsa_aes_cbc_hs(struct lws_jwe *jwe,
- char *temp, int *temp_len);
-
-int
-lws_jwe_auth_and_decrypt_cbc_hs(struct lws_jwe *jwe, uint8_t *enc_cek,
- uint8_t *aad, int aad_len);
-
-
-/* jws-rsa-aesgcm.c */
-
-int
-lws_jwe_auth_and_decrypt_gcm(struct lws_jwe *jwe, uint8_t *enc_cek,
- uint8_t *aad, int aad_len);
-
-int
-lws_jwe_auth_and_decrypt_rsa_aes_gcm(struct lws_jwe *jwe);
-
-int
-lws_jwe_encrypt_gcm(struct lws_jwe *jwe,
- uint8_t *enc_cek, uint8_t *aad, int aad_len);
-
-int
-lws_jwe_encrypt_rsa_aes_gcm(struct lws_jwe *jwe,
- char *temp, int *temp_len);
-
-
-
-
-/* jwe-rsa-aeskw.c */
-
-int
-lws_jwe_encrypt_aeskw_cbc_hs(struct lws_jwe *jwe,
- char *temp, int *temp_len);
-
-int
-lws_jwe_auth_and_decrypt_aeskw_cbc_hs(struct lws_jwe *jwe);
-
-/* aescbc.c */
-
-int
-lws_jwe_auth_and_decrypt_cbc_hs(struct lws_jwe *jwe, uint8_t *enc_cek,
- uint8_t *aad, int aad_len);
-
-int
-lws_jwe_encrypt_cbc_hs(struct lws_jwe *jwe,
- uint8_t *cek, uint8_t *aad, int aad_len);
-
-int
-lws_jwe_auth_and_decrypt_ecdh_cbc_hs(struct lws_jwe *jwe,
- char *temp, int *temp_len);
-
-int
-lws_jwe_encrypt_ecdh_cbc_hs(struct lws_jwe *jwe,
- char *temp, int *temp_len);
* MA 02110-1301 USA
*/
-#include "core/private.h"
-#include "jose/private.h"
+#include "private-lib-core.h"
+#include "private-lib-jose.h"
#if !defined(LWS_PLAT_OPTEE) && !defined(OPTEE_DEV_KIT)
#include <fcntl.h>
* to specify its JOSE JSON object. So it lives in ./lib/jose/jws/jose.c.
*/
-#include "core/private.h"
-#include "jose/private.h"
+#include "private-lib-core.h"
+#include "jose/private-lib-jose.h"
#include <stdint.h>
* MA 02110-1301 USA
*/
-#include "core/private.h"
-#include "private.h"
+#include "private-lib-core.h"
+#include "private-lib-jose-jws.h"
/*
* Currently only support flattened or compact (implicitly single signature)
--- /dev/null
+/*
+ * libwebsockets - JSON Web Signature support
+ *
+ * Copyright (C) 2018 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
+ *
+ * JOSE is actually specified as part of JWS RFC7515. JWE references RFC7515
+ * to specify its JOSE JSON object. So it lives in ./lib/jose/jws/jose.c.
+ */
+
+++ /dev/null
-/*
- * libwebsockets - JSON Web Signature support
- *
- * Copyright (C) 2018 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
- *
- * JOSE is actually specified as part of JWS RFC7515. JWE references RFC7515
- * to specify its JOSE JSON object. So it lives in ./lib/jose/jws/jose.c.
- */
-
--- /dev/null
+/*
+ * libwebsockets - jose private header
+ *
+ * Copyright (C) 2018 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
+ */
+
+void
+lws_jwk_destroy_elements(struct lws_gencrypto_keyelem *el, int m);
+
+void
+lws_jwk_init_jps(struct lejp_ctx *jctx, struct lws_jwk_parse_state *jps,
+ struct lws_jwk *jwk, lws_jwk_key_import_callback cb,
+ void *user);
+
+int
+lws_jose_render(struct lws_jose *jose, struct lws_jwk *aux_jwk,
+ char *out, size_t out_len);
+++ /dev/null
-/*
- * libwebsockets - jose private header
- *
- * Copyright (C) 2018 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
- */
-
-void
-lws_jwk_destroy_elements(struct lws_gencrypto_keyelem *el, int m);
-
-void
-lws_jwk_init_jps(struct lejp_ctx *jctx, struct lws_jwk_parse_state *jps,
- struct lws_jwk *jwk, lws_jwk_key_import_callback cb,
- void *user);
-
-int
-lws_jose_render(struct lws_jose *jose, struct lws_jwk *aux_jwk,
- char *out, size_t out_len);
#include <stdio.h>
#include <string.h>
-#include "core/private.h"
+#include "private-lib-core.h"
static const char encode_orig[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz0123456789+/";
#include <unistd.h>
#include <errno.h>
-#include "core/private.h"
+#include "private-lib-core.h"
pid_t pid_daemon;
static char *lock_path;
#define _DARWIN_C_SOURCE
#include <libwebsockets.h>
-#include "core/private.h"
+#include "private-lib-core.h"
#include <string.h>
#include <stdio.h>
#define _GNU_SOURCE
#include <pthread.h>
-#include "core/private.h"
+#include "private-lib-core.h"
#include <string.h>
#include <stdio.h>
--- /dev/null
+#include <libwebsockets.h>
+
+/* if you need > 2GB trie files */
+//typedef off_t jg2_file_offset;
+typedef uint32_t jg2_file_offset;
+
+struct lws_fts_file {
+ int fd;
+ jg2_file_offset root, flen, filepath_table;
+ int max_direct_hits;
+ int max_completion_hits;
+ int filepaths;
+};
+
+
+
+#define TRIE_FILE_HDR_SIZE 20
+#define MAX_VLI 5
+
+#define LWS_FTS_LINES_PER_CHUNK 200
+
+int
+rq32(unsigned char *b, uint32_t *d);
+++ /dev/null
-#include <libwebsockets.h>
-
-/* if you need > 2GB trie files */
-//typedef off_t jg2_file_offset;
-typedef uint32_t jg2_file_offset;
-
-struct lws_fts_file {
- int fd;
- jg2_file_offset root, flen, filepath_table;
- int max_direct_hits;
- int max_completion_hits;
- int filepaths;
-};
-
-
-
-#define TRIE_FILE_HDR_SIZE 20
-#define MAX_VLI 5
-
-#define LWS_FTS_LINES_PER_CHUNK 200
-
-int
-rq32(unsigned char *b, uint32_t *d);
* MA 02110-1301 USA
*/
-#include "core/private.h"
-#include "misc/fts/private.h"
+#include "private-lib-core.h"
+#include "private-lib-misc-fts.h"
#include <stdio.h>
#include <string.h>
* having to load it all in memory
*/
-#include "core/private.h"
-#include "misc/fts/private.h"
+#include "private-lib-core.h"
+#include "private-lib-misc-fts.h"
#include <stdio.h>
#include <string.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
-#include "core/private.h"
+#include "private-lib-core.h"
#ifdef LWS_HAVE_SYS_SOCKIO_H
#include <sys/sockio.h>
*/
#include <libwebsockets.h>
-#include "core/private.h"
+#include "private-lib-core.h"
#include <string.h>
#include <stdio.h>
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
LWS_VISIBLE LWS_EXTERN struct lws_ring *
lws_ring_create(size_t element_len, size_t count,
*/
#include <libwebsockets.h>
-#include <core/private.h>
+#include <private-lib-core.h>
#include <assert.h>
*/
#include <libwebsockets.h>
-#include <core/private.h>
+#include <private-lib-core.h>
#include <sqlite3.h>
#if !defined(LWS_PLAT_OPTEE) && !defined(OPTEE_DEV_KIT)
-#include "core/private.h"
-#include "misc/lwsac/private.h"
+#include "private-lib-core.h"
+#include "private-lib-misc-lwsac.h"
/*
* Helper for caching a file in memory in a lac, but also to check at intervals
* MA 02110-1301 USA
*/
-#include "core/private.h"
-#include "misc/lwsac/private.h"
+#include "private-lib-core.h"
+#include "private-lib-misc-lwsac.h"
void
lws_list_ptr_insert(lws_list_ptr *head, lws_list_ptr *add,
--- /dev/null
+/*
+ * libwebsockets - lws alloc chunk
+ *
+ * Copyright (C) 2018 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_PLAT_OPTEE)
+#include <sys/stat.h>
+#endif
+
+/* under page size of 4096 to allow overhead */
+#define LWSAC_CHUNK_SIZE 4000
+
+/*
+ * the chunk list members all point back to the head themselves so the list
+ * can be detached from the formal head and free itself when its reference
+ * count reaches zero.
+ */
+
+struct lwsac {
+ struct lwsac *next;
+ struct lwsac *head; /* pointer back to the first chunk */
+ struct lwsac *curr; /* applies to head chunk only */
+ size_t total_alloc_size; /* applies to head chunk only */
+ size_t alloc_size;
+ size_t ofs; /* next writeable position inside chunk */
+ int refcount; /* applies to head chunk only */
+ int total_blocks; /* applies to head chunk only */
+ char detached; /* if our refcount gets to zero, free the chunk list */
+};
+
+#if !defined(LWS_PLAT_OPTEE)
+struct cached_file_info {
+ struct stat s;
+ time_t last_confirm;
+};
+#endif
+++ /dev/null
-/*
- * libwebsockets - lws alloc chunk
- *
- * Copyright (C) 2018 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_PLAT_OPTEE)
-#include <sys/stat.h>
-#endif
-
-/* under page size of 4096 to allow overhead */
-#define LWSAC_CHUNK_SIZE 4000
-
-/*
- * the chunk list members all point back to the head themselves so the list
- * can be detached from the formal head and free itself when its reference
- * count reaches zero.
- */
-
-struct lwsac {
- struct lwsac *next;
- struct lwsac *head; /* pointer back to the first chunk */
- struct lwsac *curr; /* applies to head chunk only */
- size_t total_alloc_size; /* applies to head chunk only */
- size_t alloc_size;
- size_t ofs; /* next writeable position inside chunk */
- int refcount; /* applies to head chunk only */
- int total_blocks; /* applies to head chunk only */
- char detached; /* if our refcount gets to zero, free the chunk list */
-};
-
-#if !defined(LWS_PLAT_OPTEE)
-struct cached_file_info {
- struct stat s;
- time_t last_confirm;
-};
-#endif
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
/* requires context->lock */
static void
* implemented by Jun-ichiro itojun Itoh <itojun@itojun.org>
*/
-#include "core/private.h"
+#include "private-lib-core.h"
#ifdef LWS_HAVE_SYS_TYPES_H
#include <sys/types.h>
#define _GNU_SOURCE
#include <pthread.h>
-#include "core/private.h"
+#include "private-lib-core.h"
#include <string.h>
#include <stdio.h>
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
void
lws_plat_insert_socket_into_fds(struct lws_context *context, struct lws *wsi)
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
int lws_plat_apply_FD_CLOEXEC(int n)
{
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
-#include "misc/romfs.h"
+#include "romfs.h"
#include <esp_ota_ops.h>
#include <tcpip_adapter.h>
#include <esp_image_format.h>
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
int
lws_plat_context_early_init(void)
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
lws_usec_t
lws_now_usecs(void)
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
int
lws_plat_pipe_create(struct lws *wsi)
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
int
lws_plat_service(struct lws_context *context, int timeout_ms)
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
int
lws_send_pipe_choked(struct lws *wsi)
--- /dev/null
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010 - 2018 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
+ *
+ * Included from lib/private-lib-core.h if LWS_WITH_ESP32
+ */
+
+#define MSG_NOSIGNAL 0
+#define SOMAXCONN 3
+
+#if defined(LWS_AMAZON_RTOS)
+ int
+ open(const char *path, int oflag, ...);
+#else
+ #include <fcntl.h>
+#endif
+
+ #include <strings.h>
+ #include <unistd.h>
+ #include <sys/stat.h>
+ #include <sys/types.h>
+ #include <sys/time.h>
+ #include <netdb.h>
+
+ #ifndef __cplusplus
+ #include <errno.h>
+ #endif
+ #include <netdb.h>
+ #include <signal.h>
+#if defined(LWS_AMAZON_RTOS)
+const char *
+gai_strerror(int);
+#else
+ #include <sys/socket.h>
+#endif
+
+#if defined(LWS_AMAZON_RTOS)
+ #include "FreeRTOS.h"
+ #include "timers.h"
+ #include <esp_attr.h>
+#else
+ #include "freertos/timers.h"
+ #include <esp_attr.h>
+ #include <esp_system.h>
+ #include <esp_task_wdt.h>
+#endif
+
+#include "lwip/apps/sntp.h"
+
+#include <lwip/sockets.h>
+
+ #if defined(LWS_BUILTIN_GETIFADDRS)
+ #include "./misc/getifaddrs.h"
+ #endif
+
+ #define LWS_ERRNO errno
+ #define LWS_EAGAIN EAGAIN
+ #define LWS_EALREADY EALREADY
+ #define LWS_EINPROGRESS EINPROGRESS
+ #define LWS_EINTR EINTR
+ #define LWS_EISCONN EISCONN
+ #define LWS_ENOTCONN ENOTCONN
+ #define LWS_EWOULDBLOCK EWOULDBLOCK
+ #define LWS_EADDRINUSE EADDRINUSE
+
+ #define lws_set_blocking_send(wsi)
+
+ #ifndef LWS_NO_FORK
+ #ifdef LWS_HAVE_SYS_PRCTL_H
+ #include <sys/prctl.h>
+ #endif
+ #endif
+
+#define compatible_close(x) close(x)
+#define lws_plat_socket_offset() LWIP_SOCKET_OFFSET
+#define wsi_from_fd(A,B) A->lws_lookup[B - lws_plat_socket_offset()]
+
+struct lws_context;
+struct lws;
+
+int
+insert_wsi(const struct lws_context *context, struct lws *wsi);
+
+#define delete_from_fd(A,B) A->lws_lookup[B - lws_plat_socket_offset()] = 0
+
+++ /dev/null
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 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
- *
- * Included from lib/core/private.h if LWS_WITH_ESP32
- */
-
-#define MSG_NOSIGNAL 0
-#define SOMAXCONN 3
-
-#if defined(LWS_AMAZON_RTOS)
- int
- open(const char *path, int oflag, ...);
-#else
- #include <fcntl.h>
-#endif
-
- #include <strings.h>
- #include <unistd.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <sys/time.h>
- #include <netdb.h>
-
- #ifndef __cplusplus
- #include <errno.h>
- #endif
- #include <netdb.h>
- #include <signal.h>
-#if defined(LWS_AMAZON_RTOS)
-const char *
-gai_strerror(int);
-#else
- #include <sys/socket.h>
-#endif
-
-#if defined(LWS_AMAZON_RTOS)
- #include "FreeRTOS.h"
- #include "timers.h"
- #include <esp_attr.h>
-#else
- #include "freertos/timers.h"
- #include <esp_attr.h>
- #include <esp_system.h>
- #include <esp_task_wdt.h>
-#endif
-
-#include "lwip/apps/sntp.h"
-
-#include <lwip/sockets.h>
-
- #if defined(LWS_BUILTIN_GETIFADDRS)
- #include "./misc/getifaddrs.h"
- #endif
-
- #define LWS_ERRNO errno
- #define LWS_EAGAIN EAGAIN
- #define LWS_EALREADY EALREADY
- #define LWS_EINPROGRESS EINPROGRESS
- #define LWS_EINTR EINTR
- #define LWS_EISCONN EISCONN
- #define LWS_ENOTCONN ENOTCONN
- #define LWS_EWOULDBLOCK EWOULDBLOCK
- #define LWS_EADDRINUSE EADDRINUSE
-
- #define lws_set_blocking_send(wsi)
-
- #ifndef LWS_NO_FORK
- #ifdef LWS_HAVE_SYS_PRCTL_H
- #include <sys/prctl.h>
- #endif
- #endif
-
-#define compatible_close(x) close(x)
-#define lws_plat_socket_offset() LWIP_SOCKET_OFFSET
-#define wsi_from_fd(A,B) A->lws_lookup[B - lws_plat_socket_offset()]
-
-struct lws_context;
-struct lws;
-
-int
-insert_wsi(const struct lws_context *context, struct lws *wsi);
-
-#define delete_from_fd(A,B) A->lws_lookup[B - lws_plat_socket_offset()] = 0
-
-#include "core/private.h"
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "private-lib-core.h"
#if !defined(LWS_WITH_NETWORK)
#include <crypto/crypto.h>
-#include "core/private.h"
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "private-lib-core.h"
int
--- /dev/null
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010 - 2018 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
+ *
+ * Included from lib/private-lib-core.h if LWS_WITH_OPTEE
+ */
+
+ #include <unistd.h>
+ #include <sys/types.h>
+
+ #define LWS_ERRNO errno
+ #define LWS_EAGAIN EAGAIN
+ #define LWS_EALREADY EALREADY
+ #define LWS_EINPROGRESS EINPROGRESS
+ #define LWS_EINTR EINTR
+ #define LWS_EISCONN EISCONN
+ #define LWS_ENOTCONN ENOTCONN
+ #define LWS_EWOULDBLOCK EWOULDBLOCK
+ #define LWS_EADDRINUSE EADDRINUSE
+
+ #define lws_set_blocking_send(wsi)
+
+#define compatible_close(x) close(x)
+#define lws_plat_socket_offset() (0)
+#define wsi_from_fd(A,B) A->lws_lookup[B - lws_plat_socket_offset()]
+#define insert_wsi(A,B) assert(A->lws_lookup[B->desc.sockfd - \
+ lws_plat_socket_offset()] == 0); \
+ A->lws_lookup[B->desc.sockfd - \
+ lws_plat_socket_offset()] = B
+#define delete_from_fd(A,B) A->lws_lookup[B - lws_plat_socket_offset()] = 0
+
+++ /dev/null
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 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
- *
- * Included from lib/core/private.h if LWS_WITH_OPTEE
- */
-
- #include <unistd.h>
- #include <sys/types.h>
-
- #define LWS_ERRNO errno
- #define LWS_EAGAIN EAGAIN
- #define LWS_EALREADY EALREADY
- #define LWS_EINPROGRESS EINPROGRESS
- #define LWS_EINTR EINTR
- #define LWS_EISCONN EISCONN
- #define LWS_ENOTCONN ENOTCONN
- #define LWS_EWOULDBLOCK EWOULDBLOCK
- #define LWS_EADDRINUSE EADDRINUSE
-
- #define lws_set_blocking_send(wsi)
-
-#define compatible_close(x) close(x)
-#define lws_plat_socket_offset() (0)
-#define wsi_from_fd(A,B) A->lws_lookup[B - lws_plat_socket_offset()]
-#define insert_wsi(A,B) assert(A->lws_lookup[B->desc.sockfd - \
- lws_plat_socket_offset()] == 0); \
- A->lws_lookup[B->desc.sockfd - \
- lws_plat_socket_offset()] = B
-#define delete_from_fd(A,B) A->lws_lookup[B - lws_plat_socket_offset()] = 0
-
--- /dev/null
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010 - 2018 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
+ *
+ * Included from lib/private-lib-core.h if no explicit platform
+ */
+
+#include <fcntl.h>
+#include <strings.h>
+#include <unistd.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <poll.h>
+#include <netdb.h>
+
+#ifndef __cplusplus
+#include <errno.h>
+#endif
+#include <netdb.h>
+#include <signal.h>
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/un.h>
+
+#if defined(__APPLE__)
+#include <machine/endian.h>
+#endif
+#if defined(__FreeBSD__)
+#include <sys/endian.h>
+#endif
+#if defined(__linux__)
+#include <endian.h>
+#endif
+#if defined(__QNX__)
+ #include <gulliver.h>
+ #if defined(__LITTLEENDIAN__)
+ #define BYTE_ORDER __LITTLEENDIAN__
+ #define LITTLE_ENDIAN __LITTLEENDIAN__
+ #define BIG_ENDIAN 4321 /* to show byte order (taken from gcc); for suppres warning that BIG_ENDIAN is not defined. */
+ #endif
+ #if defined(__BIGENDIAN__)
+ #define BYTE_ORDER __BIGENDIAN__
+ #define LITTLE_ENDIAN 1234 /* to show byte order (taken from gcc); for suppres warning that LITTLE_ENDIAN is not defined. */
+ #define BIG_ENDIAN __BIGENDIAN__
+ #endif
+#endif
+
+#if defined(__sun) && defined(__GNUC__)
+
+#include <arpa/nameser_compat.h>
+
+#if !defined (BYTE_ORDER)
+#define BYTE_ORDER __BYTE_ORDER__
+#endif
+
+#if !defined(LITTLE_ENDIAN)
+#define LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__
+#endif
+
+#if !defined(BIG_ENDIAN)
+#define BIG_ENDIAN __ORDER_BIG_ENDIAN__
+#endif
+
+#endif /* sun + GNUC */
+
+#if !defined(BYTE_ORDER)
+#define BYTE_ORDER __BYTE_ORDER
+#endif
+#if !defined(LITTLE_ENDIAN)
+#define LITTLE_ENDIAN __LITTLE_ENDIAN
+#endif
+#if !defined(BIG_ENDIAN)
+#define BIG_ENDIAN __BIG_ENDIAN
+#endif
+
+#if defined(LWS_BUILTIN_GETIFADDRS)
+#include "./misc/getifaddrs.h"
+#else
+
+#if defined(__HAIKU__)
+#define _BSD_SOURCE
+#endif
+#include <ifaddrs.h>
+
+#endif
+
+#if defined (__sun) || defined(__HAIKU__) || defined(__QNX__) || defined(__ANDROID__)
+#include <syslog.h>
+
+#if defined(__ANDROID__)
+#include <sys/resource.h>
+#endif
+
+#else
+#include <sys/syslog.h>
+#endif
+
+#ifdef __QNX__
+# include "netinet/tcp_var.h"
+# define TCP_KEEPINTVL TCPCTL_KEEPINTVL
+# define TCP_KEEPIDLE TCPCTL_KEEPIDLE
+# define TCP_KEEPCNT TCPCTL_KEEPCNT
+#endif
+
+#define LWS_ERRNO errno
+#define LWS_EAGAIN EAGAIN
+#define LWS_EALREADY EALREADY
+#define LWS_EINPROGRESS EINPROGRESS
+#define LWS_EINTR EINTR
+#define LWS_EISCONN EISCONN
+#define LWS_ENOTCONN ENOTCONN
+#define LWS_EWOULDBLOCK EWOULDBLOCK
+#define LWS_EADDRINUSE EADDRINUSE
+#define lws_set_blocking_send(wsi)
+#define LWS_SOCK_INVALID (-1)
+
+struct lws_context;
+
+struct lws *
+wsi_from_fd(const struct lws_context *context, int fd);
+
+int
+insert_wsi(const struct lws_context *context, struct lws *wsi);
+
+void
+delete_from_fd(const struct lws_context *context, int fd);
+
+#ifndef LWS_NO_FORK
+#ifdef LWS_HAVE_SYS_PRCTL_H
+#include <sys/prctl.h>
+#endif
+#endif
+
+#define compatible_close(x) close(x)
+#define lws_plat_socket_offset() (0)
+
+/*
+ * Mac OSX as well as iOS do not define the MSG_NOSIGNAL flag,
+ * but happily have something equivalent in the SO_NOSIGPIPE flag.
+ */
+#ifdef __APPLE__
+#define MSG_NOSIGNAL SO_NOSIGPIPE
+#endif
+
+/*
+ * Solaris 11.X only supports POSIX 2001, MSG_NOSIGNAL appears in
+ * POSIX 2008.
+ */
+#if defined(__sun) && !defined(__smartos__)
+ #define MSG_NOSIGNAL 0
+#endif
+++ /dev/null
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 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
- *
- * Included from lib/core/private.h if no explicit platform
- */
-
-#include <fcntl.h>
-#include <strings.h>
-#include <unistd.h>
-
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <poll.h>
-#include <netdb.h>
-
-#ifndef __cplusplus
-#include <errno.h>
-#endif
-#include <netdb.h>
-#include <signal.h>
-
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/mman.h>
-#include <sys/un.h>
-
-#if defined(__APPLE__)
-#include <machine/endian.h>
-#endif
-#if defined(__FreeBSD__)
-#include <sys/endian.h>
-#endif
-#if defined(__linux__)
-#include <endian.h>
-#endif
-#if defined(__QNX__)
- #include <gulliver.h>
- #if defined(__LITTLEENDIAN__)
- #define BYTE_ORDER __LITTLEENDIAN__
- #define LITTLE_ENDIAN __LITTLEENDIAN__
- #define BIG_ENDIAN 4321 /* to show byte order (taken from gcc); for suppres warning that BIG_ENDIAN is not defined. */
- #endif
- #if defined(__BIGENDIAN__)
- #define BYTE_ORDER __BIGENDIAN__
- #define LITTLE_ENDIAN 1234 /* to show byte order (taken from gcc); for suppres warning that LITTLE_ENDIAN is not defined. */
- #define BIG_ENDIAN __BIGENDIAN__
- #endif
-#endif
-
-#if defined(__sun) && defined(__GNUC__)
-
-#include <arpa/nameser_compat.h>
-
-#if !defined (BYTE_ORDER)
-#define BYTE_ORDER __BYTE_ORDER__
-#endif
-
-#if !defined(LITTLE_ENDIAN)
-#define LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__
-#endif
-
-#if !defined(BIG_ENDIAN)
-#define BIG_ENDIAN __ORDER_BIG_ENDIAN__
-#endif
-
-#endif /* sun + GNUC */
-
-#if !defined(BYTE_ORDER)
-#define BYTE_ORDER __BYTE_ORDER
-#endif
-#if !defined(LITTLE_ENDIAN)
-#define LITTLE_ENDIAN __LITTLE_ENDIAN
-#endif
-#if !defined(BIG_ENDIAN)
-#define BIG_ENDIAN __BIG_ENDIAN
-#endif
-
-#if defined(LWS_BUILTIN_GETIFADDRS)
-#include "./misc/getifaddrs.h"
-#else
-
-#if defined(__HAIKU__)
-#define _BSD_SOURCE
-#endif
-#include <ifaddrs.h>
-
-#endif
-
-#if defined (__sun) || defined(__HAIKU__) || defined(__QNX__) || defined(__ANDROID__)
-#include <syslog.h>
-
-#if defined(__ANDROID__)
-#include <sys/resource.h>
-#endif
-
-#else
-#include <sys/syslog.h>
-#endif
-
-#ifdef __QNX__
-# include "netinet/tcp_var.h"
-# define TCP_KEEPINTVL TCPCTL_KEEPINTVL
-# define TCP_KEEPIDLE TCPCTL_KEEPIDLE
-# define TCP_KEEPCNT TCPCTL_KEEPCNT
-#endif
-
-#define LWS_ERRNO errno
-#define LWS_EAGAIN EAGAIN
-#define LWS_EALREADY EALREADY
-#define LWS_EINPROGRESS EINPROGRESS
-#define LWS_EINTR EINTR
-#define LWS_EISCONN EISCONN
-#define LWS_ENOTCONN ENOTCONN
-#define LWS_EWOULDBLOCK EWOULDBLOCK
-#define LWS_EADDRINUSE EADDRINUSE
-#define lws_set_blocking_send(wsi)
-#define LWS_SOCK_INVALID (-1)
-
-struct lws_context;
-
-struct lws *
-wsi_from_fd(const struct lws_context *context, int fd);
-
-int
-insert_wsi(const struct lws_context *context, struct lws *wsi);
-
-void
-delete_from_fd(const struct lws_context *context, int fd);
-
-#ifndef LWS_NO_FORK
-#ifdef LWS_HAVE_SYS_PRCTL_H
-#include <sys/prctl.h>
-#endif
-#endif
-
-#define compatible_close(x) close(x)
-#define lws_plat_socket_offset() (0)
-
-/*
- * Mac OSX as well as iOS do not define the MSG_NOSIGNAL flag,
- * but happily have something equivalent in the SO_NOSIGPIPE flag.
- */
-#ifdef __APPLE__
-#define MSG_NOSIGNAL SO_NOSIGPIPE
-#endif
-
-/*
- * Solaris 11.X only supports POSIX 2001, MSG_NOSIGNAL appears in
- * POSIX 2008.
- */
-#if defined(__sun) && !defined(__smartos__)
- #define MSG_NOSIGNAL 0
-#endif
*/
#define _GNU_SOURCE
-#include "core/private.h"
+#include "private-lib-core.h"
#include <pwd.h>
#include <grp.h>
*/
#define _GNU_SOURCE
-#include "core/private.h"
+#include "private-lib-core.h"
struct lws *
wsi_from_fd(const struct lws_context *context, int fd)
*/
#define _GNU_SOURCE
-#include "core/private.h"
+#include "private-lib-core.h"
#include <pwd.h>
#include <grp.h>
*/
#define _GNU_SOURCE
-#include "core/private.h"
+#include "private-lib-core.h"
#include <pwd.h>
#include <grp.h>
*/
#define _GNU_SOURCE
-#include "core/private.h"
+#include "private-lib-core.h"
lws_usec_t
lws_now_usecs(void)
*/
#define _GNU_SOURCE
-#include "core/private.h"
+#include "private-lib-core.h"
int
*/
#define _GNU_SOURCE
-#include "core/private.h"
+#include "private-lib-core.h"
#include <pwd.h>
#include <grp.h>
*/
#define _GNU_SOURCE
-#include "core/private.h"
+#include "private-lib-core.h"
int
lws_poll_listen_fd(struct lws_pollfd *fd)
*/
#define _GNU_SOURCE
-#include "core/private.h"
+#include "private-lib-core.h"
#include <pwd.h>
#include <grp.h>
--- /dev/null
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010 - 2018 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
+ *
+ * Included from lib/private-lib-core.h if defined(WIN32) || defined(_WIN32)
+ */
+
+ #ifndef WIN32_LEAN_AND_MEAN
+ #define WIN32_LEAN_AND_MEAN
+ #endif
+
+ #if defined(WINVER) && (WINVER < 0x0501)
+ #undef WINVER
+ #undef _WIN32_WINNT
+ #define WINVER 0x0501
+ #define _WIN32_WINNT WINVER
+ #endif
+
+ #define LWS_NO_DAEMONIZE
+ #define LWS_ERRNO WSAGetLastError()
+ #define LWS_EAGAIN WSAEWOULDBLOCK
+ #define LWS_EALREADY WSAEALREADY
+ #define LWS_EINPROGRESS WSAEINPROGRESS
+ #define LWS_EINTR WSAEINTR
+ #define LWS_EISCONN WSAEISCONN
+ #define LWS_ENOTCONN WSAENOTCONN
+ #define LWS_EWOULDBLOCK WSAEWOULDBLOCK
+ #define LWS_EADDRINUSE WSAEADDRINUSE
+ #define MSG_NOSIGNAL 0
+ #define SHUT_RDWR SD_BOTH
+ #define SOL_TCP IPPROTO_TCP
+ #define SHUT_WR SD_SEND
+
+ #define compatible_close(fd) closesocket(fd)
+ #define lws_set_blocking_send(wsi) wsi->sock_send_blocking = 1
+
+ #include <winsock2.h>
+ #include <ws2tcpip.h>
+ #include <windows.h>
+ #include <tchar.h>
+ #ifdef LWS_HAVE_IN6ADDR_H
+ #include <in6addr.h>
+ #endif
+ #include <mstcpip.h>
+ #include <io.h>
+
+ #if !defined(LWS_HAVE_ATOLL)
+ #if defined(LWS_HAVE__ATOI64)
+ #define atoll _atoi64
+ #else
+ #warning No atoll or _atoi64 available, using atoi
+ #define atoll atoi
+ #endif
+ #endif
+
+ #ifndef __func__
+ #define __func__ __FUNCTION__
+ #endif
+
+ #ifdef LWS_HAVE__VSNPRINTF
+ #define vsnprintf _vsnprintf
+ #endif
+
+/* we don't have an implementation for this on windows... */
+int kill(int pid, int sig);
+int fork(void);
+#ifndef SIGINT
+#define SIGINT 2
+#endif
+
+#include <gettimeofday.h>
+
+#ifndef BIG_ENDIAN
+ #define BIG_ENDIAN 4321 /* to show byte order (taken from gcc) */
+#endif
+#ifndef LITTLE_ENDIAN
+ #define LITTLE_ENDIAN 1234
+#endif
+#ifndef BYTE_ORDER
+ #define BYTE_ORDER LITTLE_ENDIAN
+#endif
+
+#undef __P
+#ifndef __P
+ #if __STDC__
+ #define __P(protos) protos
+ #else
+ #define __P(protos) ()
+ #endif
+#endif
+
+#ifdef _WIN32
+ #ifndef FD_HASHTABLE_MODULUS
+ #define FD_HASHTABLE_MODULUS 32
+ #endif
+#endif
+
+#define lws_plat_socket_offset() (0)
+
+struct lws;
+struct lws_context;
+
+#define LWS_FD_HASH(fd) ((fd ^ (fd >> 8) ^ (fd >> 16)) % FD_HASHTABLE_MODULUS)
+struct lws_fd_hashtable {
+ struct lws **wsi;
+ int length;
+};
+
+
+#ifdef LWS_DLL
+#ifdef LWS_INTERNAL
+#define LWS_EXTERN extern __declspec(dllexport)
+#else
+#define LWS_EXTERN extern __declspec(dllimport)
+#endif
+#else
+#define LWS_EXTERN
+#endif
+
+typedef SOCKET lws_sockfd_type;
+typedef HANDLE lws_filefd_type;
+#define LWS_WIN32_HANDLE_TYPES
+
+LWS_EXTERN struct lws *
+wsi_from_fd(const struct lws_context *context, lws_sockfd_type fd);
+
+LWS_EXTERN int
+insert_wsi(struct lws_context *context, struct lws *wsi);
+
+LWS_EXTERN int
+delete_from_fd(struct lws_context *context, lws_sockfd_type fd);
+++ /dev/null
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 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
- *
- * Included from lib/core/private.h if defined(WIN32) || defined(_WIN32)
- */
-
- #ifndef WIN32_LEAN_AND_MEAN
- #define WIN32_LEAN_AND_MEAN
- #endif
-
- #if defined(WINVER) && (WINVER < 0x0501)
- #undef WINVER
- #undef _WIN32_WINNT
- #define WINVER 0x0501
- #define _WIN32_WINNT WINVER
- #endif
-
- #define LWS_NO_DAEMONIZE
- #define LWS_ERRNO WSAGetLastError()
- #define LWS_EAGAIN WSAEWOULDBLOCK
- #define LWS_EALREADY WSAEALREADY
- #define LWS_EINPROGRESS WSAEINPROGRESS
- #define LWS_EINTR WSAEINTR
- #define LWS_EISCONN WSAEISCONN
- #define LWS_ENOTCONN WSAENOTCONN
- #define LWS_EWOULDBLOCK WSAEWOULDBLOCK
- #define LWS_EADDRINUSE WSAEADDRINUSE
- #define MSG_NOSIGNAL 0
- #define SHUT_RDWR SD_BOTH
- #define SOL_TCP IPPROTO_TCP
- #define SHUT_WR SD_SEND
-
- #define compatible_close(fd) closesocket(fd)
- #define lws_set_blocking_send(wsi) wsi->sock_send_blocking = 1
-
- #include <winsock2.h>
- #include <ws2tcpip.h>
- #include <windows.h>
- #include <tchar.h>
- #ifdef LWS_HAVE_IN6ADDR_H
- #include <in6addr.h>
- #endif
- #include <mstcpip.h>
- #include <io.h>
-
- #if !defined(LWS_HAVE_ATOLL)
- #if defined(LWS_HAVE__ATOI64)
- #define atoll _atoi64
- #else
- #warning No atoll or _atoi64 available, using atoi
- #define atoll atoi
- #endif
- #endif
-
- #ifndef __func__
- #define __func__ __FUNCTION__
- #endif
-
- #ifdef LWS_HAVE__VSNPRINTF
- #define vsnprintf _vsnprintf
- #endif
-
-/* we don't have an implementation for this on windows... */
-int kill(int pid, int sig);
-int fork(void);
-#ifndef SIGINT
-#define SIGINT 2
-#endif
-
-#include <gettimeofday.h>
-
-#ifndef BIG_ENDIAN
- #define BIG_ENDIAN 4321 /* to show byte order (taken from gcc) */
-#endif
-#ifndef LITTLE_ENDIAN
- #define LITTLE_ENDIAN 1234
-#endif
-#ifndef BYTE_ORDER
- #define BYTE_ORDER LITTLE_ENDIAN
-#endif
-
-#undef __P
-#ifndef __P
- #if __STDC__
- #define __P(protos) protos
- #else
- #define __P(protos) ()
- #endif
-#endif
-
-#ifdef _WIN32
- #ifndef FD_HASHTABLE_MODULUS
- #define FD_HASHTABLE_MODULUS 32
- #endif
-#endif
-
-#define lws_plat_socket_offset() (0)
-
-struct lws;
-struct lws_context;
-
-#define LWS_FD_HASH(fd) ((fd ^ (fd >> 8) ^ (fd >> 16)) % FD_HASHTABLE_MODULUS)
-struct lws_fd_hashtable {
- struct lws **wsi;
- int length;
-};
-
-
-#ifdef LWS_DLL
-#ifdef LWS_INTERNAL
-#define LWS_EXTERN extern __declspec(dllexport)
-#else
-#define LWS_EXTERN extern __declspec(dllimport)
-#endif
-#else
-#define LWS_EXTERN
-#endif
-
-typedef SOCKET lws_sockfd_type;
-typedef HANDLE lws_filefd_type;
-#define LWS_WIN32_HANDLE_TYPES
-
-LWS_EXTERN struct lws *
-wsi_from_fd(const struct lws_context *context, lws_sockfd_type fd);
-
-LWS_EXTERN int
-insert_wsi(struct lws_context *context, struct lws *wsi);
-
-LWS_EXTERN int
-delete_from_fd(struct lws_context *context, lws_sockfd_type fd);
#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#endif
-#include "core/private.h"
+#include "private-lib-core.h"
struct lws *
wsi_from_fd(const struct lws_context *context, lws_sockfd_type fd)
#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#endif
-#include "core/private.h"
+#include "private-lib-core.h"
int lws_plat_apply_FD_CLOEXEC(int n)
{
#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#endif
-#include "core/private.h"
+#include "private-lib-core.h"
int
lws_plat_drop_app_privileges(struct lws_context *context, int actually_set)
#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#endif
-#include "core/private.h"
+#include "private-lib-core.h"
lws_usec_t
#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#endif
-#include "core/private.h"
+#include "private-lib-core.h"
int
lws_plat_pipe_create(struct lws *wsi)
#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#endif
-#include "core/private.h"
+#include "private-lib-core.h"
int
lws_plat_plugins_init(struct lws_context * context, const char * const *d)
#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#endif
-#include "core/private.h"
+#include "private-lib-core.h"
LWS_EXTERN int
#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#endif
-#include "core/private.h"
+#include "private-lib-core.h"
LWS_VISIBLE int
### Role ops struct
-The role is defined by `struct lws_role_ops` in `lib/roles/private.h`,
+The role is defined by `struct lws_role_ops` in `lib/roles/private-lib-roles.h`,
each role instantiates one of these and fills in the appropriate ops
callbacks to perform its job. By convention that lives in
`./lib/roles/**role name**/ops-**role_name**.c`.
Truly private declarations for the role can go in the role directory as you like.
However when the declarations must be accessible to other things in lws build, eg,
the role adds members to `struct lws` when enabled, they should be in the role
-directory in a file `private.h`.
+directory in a file `private-lib-roles-myrole.h`.
-Search for "bring in role private declarations" in `./lib/roles/private.h
+Search for "bring in role private declarations" in `./lib/roles/private-lib-roles.h
and add your private role file there following the style used for the other roles,
eg,
```
#if defined(LWS_ROLE_WS)
- #include "roles/ws/private.h"
+ #include "roles/ws/private-lib-roles-ws.h"
#else
#define lwsi_role_ws(wsi) (0)
#endif
#define _GNU_SOURCE
-#include "core/private.h"
+#include "private-lib-core.h"
#if defined(WIN32) || defined(_WIN32)
#else
* MA 02110-1301 USA
*/
-#include <core/private.h>
+#include <private-lib-core.h>
static int
rops_handle_POLLIN_cgi(struct lws_context_per_thread *pt, struct lws *wsi,
--- /dev/null
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010 - 2018 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
+ *
+ * This is included from private-lib-core.h if LWS_ROLE_WS
+ */
+
+#if defined(LWS_WITH_ZLIB)
+#if defined(LWS_WITH_MINIZ)
+#include <miniz.h>
+#else
+#include <zlib.h>
+#endif
+#endif
+
+extern struct lws_role_ops role_ops_cgi;
+
+#define lwsi_role_cgi(wsi) (wsi->role_ops == &role_ops_cgi)
+
+#define LWS_HTTP_CHUNK_HDR_SIZE 16
+
+enum {
+ SIGNIFICANT_HDR_CONTENT_LENGTH, /* numeric */
+ SIGNIFICANT_HDR_LOCATION,
+ SIGNIFICANT_HDR_STATUS, /* numeric */
+ SIGNIFICANT_HDR_TRANSFER_ENCODING,
+ SIGNIFICANT_HDR_CONTENT_ENCODING_GZIP,
+
+ SIGNIFICANT_HDR_COUNT
+};
+
+struct lws;
+
+/* wsi who is master of the cgi points to an lws_cgi */
+
+struct lws_cgi {
+ struct lws_cgi *cgi_list;
+ struct lws *stdwsi[3]; /* points to the associated stdin/out/err wsis */
+ struct lws *wsi; /* owner */
+ unsigned char *headers_buf;
+ unsigned char *headers_start;
+ unsigned char *headers_pos;
+ unsigned char *headers_dumped;
+ unsigned char *headers_end;
+
+ char summary[128];
+#if defined(LWS_WITH_ZLIB)
+ z_stream inflate;
+ uint8_t inflate_buf[1024];
+#endif
+
+ lws_filepos_t post_in_expected;
+ lws_filepos_t content_length;
+ lws_filepos_t content_length_seen;
+
+ int pipe_fds[3][2];
+ int match[SIGNIFICANT_HDR_COUNT];
+ char l[12];
+ int pid;
+ int response_code;
+ int lp;
+
+ unsigned char being_closed:1;
+ unsigned char explicitly_chunked:1;
+ unsigned char cgi_transaction_over:1;
+ unsigned char implied_chunked:1;
+ unsigned char gzip_inflate:1;
+ unsigned char gzip_init:1;
+
+ unsigned char chunked_grace;
+};
+++ /dev/null
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 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
- *
- * This is included from core/private.h if LWS_ROLE_WS
- */
-
-#if defined(LWS_WITH_ZLIB)
-#if defined(LWS_WITH_MINIZ)
-#include <miniz.h>
-#else
-#include <zlib.h>
-#endif
-#endif
-
-extern struct lws_role_ops role_ops_cgi;
-
-#define lwsi_role_cgi(wsi) (wsi->role_ops == &role_ops_cgi)
-
-#define LWS_HTTP_CHUNK_HDR_SIZE 16
-
-enum {
- SIGNIFICANT_HDR_CONTENT_LENGTH, /* numeric */
- SIGNIFICANT_HDR_LOCATION,
- SIGNIFICANT_HDR_STATUS, /* numeric */
- SIGNIFICANT_HDR_TRANSFER_ENCODING,
- SIGNIFICANT_HDR_CONTENT_ENCODING_GZIP,
-
- SIGNIFICANT_HDR_COUNT
-};
-
-struct lws;
-
-/* wsi who is master of the cgi points to an lws_cgi */
-
-struct lws_cgi {
- struct lws_cgi *cgi_list;
- struct lws *stdwsi[3]; /* points to the associated stdin/out/err wsis */
- struct lws *wsi; /* owner */
- unsigned char *headers_buf;
- unsigned char *headers_start;
- unsigned char *headers_pos;
- unsigned char *headers_dumped;
- unsigned char *headers_end;
-
- char summary[128];
-#if defined(LWS_WITH_ZLIB)
- z_stream inflate;
- uint8_t inflate_buf[1024];
-#endif
-
- lws_filepos_t post_in_expected;
- lws_filepos_t content_length;
- lws_filepos_t content_length_seen;
-
- int pipe_fds[3][2];
- int match[SIGNIFICANT_HDR_COUNT];
- char l[12];
- int pid;
- int response_code;
- int lp;
-
- unsigned char being_closed:1;
- unsigned char explicitly_chunked:1;
- unsigned char cgi_transaction_over:1;
- unsigned char implied_chunked:1;
- unsigned char gzip_inflate:1;
- unsigned char gzip_init:1;
-
- unsigned char chunked_grace;
-};
* worries we create a new shadow wsi until it looks like it is closing again.
*/
-#include <core/private.h>
+#include <private-lib-core.h>
#include <libwebsockets/lws-dbus.h>
--- /dev/null
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010 - 2018 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
+ *
+ * This is included from private-lib-core.h if LWS_ROLE_DBUS
+ */
+
+#include <dbus/dbus.h>
+
+extern struct lws_role_ops role_ops_dbus;
+
+#define lwsi_role_dbus(wsi) (wsi->role_ops == &role_ops_dbus)
+
+struct lws_role_dbus_timer {
+ struct lws_dll2 timer_list;
+ void *data;
+ time_t fire;
+};
+
+struct lws_pt_role_dbus {
+ struct lws_dll2_owner timer_list_owner;
+};
+
+struct _lws_dbus_mode_related {
+ DBusConnection *conn;
+};
+++ /dev/null
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 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
- *
- * This is included from core/private.h if LWS_ROLE_DBUS
- */
-
-#include <dbus/dbus.h>
-
-extern struct lws_role_ops role_ops_dbus;
-
-#define lwsi_role_dbus(wsi) (wsi->role_ops == &role_ops_dbus)
-
-struct lws_role_dbus_timer {
- struct lws_dll2 timer_list;
- void *data;
- time_t fire;
-};
-
-struct lws_pt_role_dbus {
- struct lws_dll2_owner timer_list_owner;
-};
-
-struct _lws_dbus_mode_related {
- DBusConnection *conn;
-};
* MA 02110-1301 USA
*/
-#include <core/private.h>
+#include <private-lib-core.h>
#ifndef min
#define min(a, b) ((a) < (b) ? (a) : (b))
--- /dev/null
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010 - 2018 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
+ *
+ * This is included from private-lib-core.h if LWS_ROLE_H1
+ *
+ * Most of the h1 business is defined in the h1 / h2 common roles/http dir
+ */
+
+extern struct lws_role_ops role_ops_h1;
+#define lwsi_role_h1(wsi) (wsi->role_ops == &role_ops_h1)
+++ /dev/null
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 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
- *
- * This is included from core/private.h if LWS_ROLE_H1
- *
- * Most of the h1 business is defined in the h1 / h2 common roles/http dir
- */
-
-extern struct lws_role_ops role_ops_h1;
-#define lwsi_role_h1(wsi) (wsi->role_ops == &role_ops_h1)
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
/*
* Official static header table for HPACK
* MA 02110-1301 USA
*/
-
-#include "core/private.h"
+#include "private-lib-core.h"
/*
* bitmap of control messages that are valid to receive for each http2 state
* MA 02110-1301 USA
*/
-#include <core/private.h>
+#include <private-lib-core.h>
/*
* These are the standardized defaults.
--- /dev/null
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010 - 2018 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
+ *
+ * This is included from core/private.h if LWS_ROLE_H2
+ */
+
+extern struct lws_role_ops role_ops_h2;
+#define lwsi_role_h2(wsi) (wsi->role_ops == &role_ops_h2)
+
+enum lws_h2_settings {
+ H2SET_HEADER_TABLE_SIZE = 1,
+ H2SET_ENABLE_PUSH,
+ H2SET_MAX_CONCURRENT_STREAMS,
+ H2SET_INITIAL_WINDOW_SIZE,
+ H2SET_MAX_FRAME_SIZE,
+ H2SET_MAX_HEADER_LIST_SIZE,
+ H2SET_RESERVED7,
+ H2SET_ENABLE_CONNECT_PROTOCOL, /* defined in mcmanus-httpbis-h2-ws-02 */
+
+ H2SET_COUNT /* always last */
+};
+
+struct http2_settings {
+ uint32_t s[H2SET_COUNT];
+};
+
+struct lws_vhost_role_h2 {
+ struct http2_settings set;
+};
+
+enum lws_h2_wellknown_frame_types {
+ LWS_H2_FRAME_TYPE_DATA,
+ LWS_H2_FRAME_TYPE_HEADERS,
+ LWS_H2_FRAME_TYPE_PRIORITY,
+ LWS_H2_FRAME_TYPE_RST_STREAM,
+ LWS_H2_FRAME_TYPE_SETTINGS,
+ LWS_H2_FRAME_TYPE_PUSH_PROMISE,
+ LWS_H2_FRAME_TYPE_PING,
+ LWS_H2_FRAME_TYPE_GOAWAY,
+ LWS_H2_FRAME_TYPE_WINDOW_UPDATE,
+ LWS_H2_FRAME_TYPE_CONTINUATION,
+
+ LWS_H2_FRAME_TYPE_COUNT /* always last */
+};
+
+enum lws_h2_flags {
+ LWS_H2_FLAG_END_STREAM = 1,
+ LWS_H2_FLAG_END_HEADERS = 4,
+ LWS_H2_FLAG_PADDED = 8,
+ LWS_H2_FLAG_PRIORITY = 0x20,
+
+ LWS_H2_FLAG_SETTINGS_ACK = 1,
+};
+
+enum lws_h2_errors {
+ H2_ERR_NO_ERROR, /* Graceful shutdown */
+ H2_ERR_PROTOCOL_ERROR, /* Protocol error detected */
+ H2_ERR_INTERNAL_ERROR, /* Implementation fault */
+ H2_ERR_FLOW_CONTROL_ERROR, /* Flow-control limits exceeded */
+ H2_ERR_SETTINGS_TIMEOUT, /* Settings not acknowledged */
+ H2_ERR_STREAM_CLOSED, /* Frame received for closed stream */
+ H2_ERR_FRAME_SIZE_ERROR, /* Frame size incorrect */
+ H2_ERR_REFUSED_STREAM, /* Stream not processed */
+ H2_ERR_CANCEL, /* Stream cancelled */
+ H2_ERR_COMPRESSION_ERROR, /* Compression state not updated */
+ H2_ERR_CONNECT_ERROR, /* TCP connection error for CONNECT method */
+ H2_ERR_ENHANCE_YOUR_CALM, /* Processing capacity exceeded */
+ H2_ERR_INADEQUATE_SECURITY, /* Negotiated TLS parameters not acceptable */
+ H2_ERR_HTTP_1_1_REQUIRED, /* Use HTTP/1.1 for the request */
+};
+
+enum lws_h2_states {
+ LWS_H2_STATE_IDLE,
+ /*
+ * Send PUSH_PROMISE -> LWS_H2_STATE_RESERVED_LOCAL
+ * Recv PUSH_PROMISE -> LWS_H2_STATE_RESERVED_REMOTE
+ * Send HEADERS -> LWS_H2_STATE_OPEN
+ * Recv HEADERS -> LWS_H2_STATE_OPEN
+ *
+ * - Only PUSH_PROMISE + HEADERS valid to send
+ * - Only HEADERS or PRIORITY valid to receive
+ */
+ LWS_H2_STATE_RESERVED_LOCAL,
+ /*
+ * Send RST_STREAM -> LWS_H2_STATE_CLOSED
+ * Recv RST_STREAM -> LWS_H2_STATE_CLOSED
+ * Send HEADERS -> LWS_H2_STATE_HALF_CLOSED_REMOTE
+ *
+ * - Only HEADERS, RST_STREAM, or PRIORITY valid to send
+ * - Only RST_STREAM, PRIORITY, or WINDOW_UPDATE valid to receive
+ */
+ LWS_H2_STATE_RESERVED_REMOTE,
+ /*
+ * Send RST_STREAM -> LWS_H2_STATE_CLOSED
+ * Recv RST_STREAM -> LWS_H2_STATE_CLOSED
+ * Recv HEADERS -> LWS_H2_STATE_HALF_CLOSED_LOCAL
+ *
+ * - Only RST_STREAM, WINDOW_UPDATE, or PRIORITY valid to send
+ * - Only HEADERS, RST_STREAM, or PRIORITY valid to receive
+ */
+ LWS_H2_STATE_OPEN,
+ /*
+ * Send RST_STREAM -> LWS_H2_STATE_CLOSED
+ * Recv RST_STREAM -> LWS_H2_STATE_CLOSED
+ * Send END_STREAM flag -> LWS_H2_STATE_HALF_CLOSED_LOCAL
+ * Recv END_STREAM flag -> LWS_H2_STATE_HALF_CLOSED_REMOTE
+ */
+ LWS_H2_STATE_HALF_CLOSED_REMOTE,
+ /*
+ * Send RST_STREAM -> LWS_H2_STATE_CLOSED
+ * Recv RST_STREAM -> LWS_H2_STATE_CLOSED
+ * Send END_STREAM flag -> LWS_H2_STATE_CLOSED
+ *
+ * - Any frame valid to send
+ * - Only WINDOW_UPDATE, PRIORITY, or RST_STREAM valid to receive
+ */
+ LWS_H2_STATE_HALF_CLOSED_LOCAL,
+ /*
+ * Send RST_STREAM -> LWS_H2_STATE_CLOSED
+ * Recv RST_STREAM -> LWS_H2_STATE_CLOSED
+ * Recv END_STREAM flag -> LWS_H2_STATE_CLOSED
+ *
+ * - Only WINDOW_UPDATE, PRIORITY, and RST_STREAM valid to send
+ * - Any frame valid to receive
+ */
+ LWS_H2_STATE_CLOSED,
+ /*
+ * - Only PRIORITY, WINDOW_UPDATE (IGNORE) and RST_STREAM (IGNORE)
+ * may be received
+ *
+ * - Only PRIORITY valid to send
+ */
+};
+
+void
+lws_h2_state(struct lws *wsi, enum lws_h2_states s);
+
+#define LWS_H2_STREAM_ID_MASTER 0
+#define LWS_H2_SETTINGS_LEN 6
+#define LWS_H2_FLAG_SETTINGS_ACK 1
+
+enum http2_hpack_state {
+ HPKS_TYPE,
+
+ HPKS_IDX_EXT,
+
+ HPKS_HLEN,
+ HPKS_HLEN_EXT,
+
+ HPKS_DATA,
+};
+
+/*
+ * lws general parsimonious header strategy is only store values from known
+ * headers, and refer to them by index.
+ *
+ * That means if we can't map the peer header name to one that lws knows, we
+ * will drop the content but track the indexing with associated_lws_hdr_idx =
+ * LWS_HPACK_IGNORE_ENTRY.
+ */
+
+enum http2_hpack_type {
+ HPKT_INDEXED_HDR_7, /* 1xxxxxxx: just "header field" */
+ HPKT_INDEXED_HDR_6_VALUE_INCR, /* 01xxxxxx: NEW indexed hdr with value */
+ HPKT_LITERAL_HDR_VALUE_INCR, /* 01000000: NEW literal hdr with value */
+ HPKT_INDEXED_HDR_4_VALUE, /* 0000xxxx: indexed hdr with value */
+ HPKT_INDEXED_HDR_4_VALUE_NEVER, /* 0001xxxx: indexed hdr with value NEVER NEW */
+ HPKT_LITERAL_HDR_VALUE, /* 00000000: literal hdr with value */
+ HPKT_LITERAL_HDR_VALUE_NEVER, /* 00010000: literal hdr with value NEVER NEW */
+ HPKT_SIZE_5
+};
+
+#define LWS_HPACK_IGNORE_ENTRY 0xffff
+
+
+struct hpack_dt_entry {
+ char *value; /* malloc'd */
+ uint16_t value_len;
+ uint16_t hdr_len; /* virtual, for accounting */
+ uint16_t lws_hdr_idx; /* LWS_HPACK_IGNORE_ENTRY = IGNORE */
+};
+
+struct hpack_dynamic_table {
+ struct hpack_dt_entry *entries; /* malloc'd */
+ uint32_t virtual_payload_usage;
+ uint32_t virtual_payload_max;
+ uint16_t pos;
+ uint16_t used_entries;
+ uint16_t num_entries;
+};
+
+enum lws_h2_protocol_send_type {
+ LWS_PPS_NONE,
+ LWS_H2_PPS_MY_SETTINGS,
+ LWS_H2_PPS_ACK_SETTINGS,
+ LWS_H2_PPS_PONG,
+ LWS_H2_PPS_GOAWAY,
+ LWS_H2_PPS_RST_STREAM,
+ LWS_H2_PPS_UPDATE_WINDOW,
+};
+
+struct lws_h2_protocol_send {
+ struct lws_h2_protocol_send *next; /* linked list */
+ enum lws_h2_protocol_send_type type;
+
+ union uu {
+ struct {
+ char str[32];
+ uint32_t highest_sid;
+ uint32_t err;
+ } ga;
+ struct {
+ uint32_t sid;
+ uint32_t err;
+ } rs;
+ struct {
+ uint8_t ping_payload[8];
+ } ping;
+ struct {
+ uint32_t sid;
+ uint32_t credit;
+ } update_window;
+ } u;
+};
+
+struct lws_h2_ghost_sid {
+ struct lws_h2_ghost_sid *next;
+ uint32_t sid;
+};
+
+/*
+ * http/2 connection info that is only used by the root connection that has
+ * the network connection.
+ *
+ * h2 tends to spawn many child connections from one network connection, so
+ * it's necessary to make members only needed by the network connection
+ * distinct and only malloc'd on network connections.
+ *
+ * There's only one HPACK parser per network connection.
+ *
+ * But there is an ah per logical child connection... the network connection
+ * fills it but it belongs to the logical child.
+ */
+struct lws_h2_netconn {
+ struct http2_settings set;
+ struct hpack_dynamic_table hpack_dyn_table;
+ uint8_t ping_payload[8];
+ uint8_t one_setting[LWS_H2_SETTINGS_LEN];
+ char goaway_str[32]; /* for rx */
+ struct lws *swsi;
+ struct lws_h2_protocol_send *pps; /* linked list */
+
+ enum http2_hpack_state hpack;
+ enum http2_hpack_type hpack_type;
+
+ unsigned int huff:1;
+ unsigned int value:1;
+ unsigned int unknown_header:1;
+ unsigned int cont_exp:1;
+ unsigned int cont_exp_headers:1;
+ unsigned int we_told_goaway:1;
+ unsigned int pad_length:1;
+ unsigned int collected_priority:1;
+ unsigned int is_first_header_char:1;
+ unsigned int zero_huff_padding:1;
+ unsigned int last_action_dyntable_resize:1;
+
+ uint32_t hdr_idx;
+ uint32_t hpack_len;
+ uint32_t hpack_e_dep;
+ uint32_t count;
+ uint32_t preamble;
+ uint32_t length;
+ uint32_t sid;
+ uint32_t inside;
+ uint32_t highest_sid;
+ uint32_t highest_sid_opened;
+ uint32_t cont_exp_sid;
+ uint32_t dep;
+ uint32_t goaway_last_sid;
+ uint32_t goaway_err;
+ uint32_t hpack_hdr_len;
+
+ uint16_t hpack_pos;
+
+ uint8_t frame_state;
+ uint8_t type;
+ uint8_t flags;
+ uint8_t padding;
+ uint8_t weight_temp;
+ uint8_t huff_pad;
+ char first_hdr_char;
+ uint8_t hpack_m;
+ uint8_t ext_count;
+};
+
+struct _lws_h2_related {
+
+ struct lws_h2_netconn *h2n; /* malloc'd for root net conn */
+ struct lws *parent_wsi;
+ struct lws *child_list;
+ struct lws *sibling_list;
+
+ char *pending_status_body;
+
+ int tx_cr;
+ int peer_tx_cr_est;
+ unsigned int my_sid;
+ unsigned int child_count;
+ int my_priority;
+ uint32_t dependent_on;
+
+ unsigned int END_STREAM:1;
+ unsigned int END_HEADERS:1;
+ unsigned int send_END_STREAM:1;
+ unsigned int GOING_AWAY;
+ unsigned int requested_POLLOUT:1;
+ unsigned int skint:1;
+
+ uint16_t round_robin_POLLOUT;
+ uint16_t count_POLLOUT_children;
+
+ uint8_t h2_state; /* the RFC7540 state of the connection */
+ uint8_t weight;
+ uint8_t initialized;
+};
+
+#define HTTP2_IS_TOPLEVEL_WSI(wsi) (!wsi->h2.parent_wsi)
+
+int
+lws_h2_rst_stream(struct lws *wsi, uint32_t err, const char *reason);
+struct lws * lws_h2_get_nth_child(struct lws *wsi, int n);
+LWS_EXTERN void lws_h2_init(struct lws *wsi);
+LWS_EXTERN int
+lws_h2_settings(struct lws *nwsi, struct http2_settings *settings,
+ unsigned char *buf, int len);
+LWS_EXTERN int
+lws_h2_parser(struct lws *wsi, unsigned char *in, lws_filepos_t inlen,
+ lws_filepos_t *inused);
+LWS_EXTERN int
+lws_h2_do_pps_send(struct lws *wsi);
+LWS_EXTERN int
+lws_h2_frame_write(struct lws *wsi, int type, int flags, unsigned int sid,
+ unsigned int len, unsigned char *buf);
+LWS_EXTERN struct lws *
+lws_h2_wsi_from_id(struct lws *wsi, unsigned int sid);
+LWS_EXTERN int
+lws_hpack_interpret(struct lws *wsi, unsigned char c);
+LWS_EXTERN int
+lws_add_http2_header_by_name(struct lws *wsi,
+ const unsigned char *name,
+ const unsigned char *value, int length,
+ unsigned char **p, unsigned char *end);
+LWS_EXTERN int
+lws_add_http2_header_by_token(struct lws *wsi,
+ enum lws_token_indexes token,
+ const unsigned char *value, int length,
+ unsigned char **p, unsigned char *end);
+LWS_EXTERN int
+lws_add_http2_header_status(struct lws *wsi,
+ unsigned int code, unsigned char **p,
+ unsigned char *end);
+LWS_EXTERN void
+lws_hpack_destroy_dynamic_header(struct lws *wsi);
+LWS_EXTERN int
+lws_hpack_dynamic_size(struct lws *wsi, int size);
+LWS_EXTERN int
+lws_h2_goaway(struct lws *wsi, uint32_t err, const char *reason);
+LWS_EXTERN int
+lws_h2_tx_cr_get(struct lws *wsi);
+LWS_EXTERN void
+lws_h2_tx_cr_consume(struct lws *wsi, int consumed);
+LWS_EXTERN int
+lws_hdr_extant(struct lws *wsi, enum lws_token_indexes h);
+LWS_EXTERN void
+lws_pps_schedule(struct lws *wsi, struct lws_h2_protocol_send *pss);
+
+LWS_EXTERN const struct http2_settings lws_h2_defaults;
+LWS_EXTERN int
+lws_h2_ws_handshake(struct lws *wsi);
+LWS_EXTERN int lws_h2_issue_preface(struct lws *wsi);
+LWS_EXTERN int
+lws_h2_client_handshake(struct lws *wsi);
+LWS_EXTERN struct lws *
+lws_wsi_h2_adopt(struct lws *parent_wsi, struct lws *wsi);
+int
+lws_handle_POLLOUT_event_h2(struct lws *wsi);
+int
+lws_read_h2(struct lws *wsi, unsigned char *buf, lws_filepos_t len);
+++ /dev/null
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 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
- *
- * This is included from core/private.h if LWS_ROLE_H2
- */
-
-extern struct lws_role_ops role_ops_h2;
-#define lwsi_role_h2(wsi) (wsi->role_ops == &role_ops_h2)
-
-enum lws_h2_settings {
- H2SET_HEADER_TABLE_SIZE = 1,
- H2SET_ENABLE_PUSH,
- H2SET_MAX_CONCURRENT_STREAMS,
- H2SET_INITIAL_WINDOW_SIZE,
- H2SET_MAX_FRAME_SIZE,
- H2SET_MAX_HEADER_LIST_SIZE,
- H2SET_RESERVED7,
- H2SET_ENABLE_CONNECT_PROTOCOL, /* defined in mcmanus-httpbis-h2-ws-02 */
-
- H2SET_COUNT /* always last */
-};
-
-struct http2_settings {
- uint32_t s[H2SET_COUNT];
-};
-
-struct lws_vhost_role_h2 {
- struct http2_settings set;
-};
-
-enum lws_h2_wellknown_frame_types {
- LWS_H2_FRAME_TYPE_DATA,
- LWS_H2_FRAME_TYPE_HEADERS,
- LWS_H2_FRAME_TYPE_PRIORITY,
- LWS_H2_FRAME_TYPE_RST_STREAM,
- LWS_H2_FRAME_TYPE_SETTINGS,
- LWS_H2_FRAME_TYPE_PUSH_PROMISE,
- LWS_H2_FRAME_TYPE_PING,
- LWS_H2_FRAME_TYPE_GOAWAY,
- LWS_H2_FRAME_TYPE_WINDOW_UPDATE,
- LWS_H2_FRAME_TYPE_CONTINUATION,
-
- LWS_H2_FRAME_TYPE_COUNT /* always last */
-};
-
-enum lws_h2_flags {
- LWS_H2_FLAG_END_STREAM = 1,
- LWS_H2_FLAG_END_HEADERS = 4,
- LWS_H2_FLAG_PADDED = 8,
- LWS_H2_FLAG_PRIORITY = 0x20,
-
- LWS_H2_FLAG_SETTINGS_ACK = 1,
-};
-
-enum lws_h2_errors {
- H2_ERR_NO_ERROR, /* Graceful shutdown */
- H2_ERR_PROTOCOL_ERROR, /* Protocol error detected */
- H2_ERR_INTERNAL_ERROR, /* Implementation fault */
- H2_ERR_FLOW_CONTROL_ERROR, /* Flow-control limits exceeded */
- H2_ERR_SETTINGS_TIMEOUT, /* Settings not acknowledged */
- H2_ERR_STREAM_CLOSED, /* Frame received for closed stream */
- H2_ERR_FRAME_SIZE_ERROR, /* Frame size incorrect */
- H2_ERR_REFUSED_STREAM, /* Stream not processed */
- H2_ERR_CANCEL, /* Stream cancelled */
- H2_ERR_COMPRESSION_ERROR, /* Compression state not updated */
- H2_ERR_CONNECT_ERROR, /* TCP connection error for CONNECT method */
- H2_ERR_ENHANCE_YOUR_CALM, /* Processing capacity exceeded */
- H2_ERR_INADEQUATE_SECURITY, /* Negotiated TLS parameters not acceptable */
- H2_ERR_HTTP_1_1_REQUIRED, /* Use HTTP/1.1 for the request */
-};
-
-enum lws_h2_states {
- LWS_H2_STATE_IDLE,
- /*
- * Send PUSH_PROMISE -> LWS_H2_STATE_RESERVED_LOCAL
- * Recv PUSH_PROMISE -> LWS_H2_STATE_RESERVED_REMOTE
- * Send HEADERS -> LWS_H2_STATE_OPEN
- * Recv HEADERS -> LWS_H2_STATE_OPEN
- *
- * - Only PUSH_PROMISE + HEADERS valid to send
- * - Only HEADERS or PRIORITY valid to receive
- */
- LWS_H2_STATE_RESERVED_LOCAL,
- /*
- * Send RST_STREAM -> LWS_H2_STATE_CLOSED
- * Recv RST_STREAM -> LWS_H2_STATE_CLOSED
- * Send HEADERS -> LWS_H2_STATE_HALF_CLOSED_REMOTE
- *
- * - Only HEADERS, RST_STREAM, or PRIORITY valid to send
- * - Only RST_STREAM, PRIORITY, or WINDOW_UPDATE valid to receive
- */
- LWS_H2_STATE_RESERVED_REMOTE,
- /*
- * Send RST_STREAM -> LWS_H2_STATE_CLOSED
- * Recv RST_STREAM -> LWS_H2_STATE_CLOSED
- * Recv HEADERS -> LWS_H2_STATE_HALF_CLOSED_LOCAL
- *
- * - Only RST_STREAM, WINDOW_UPDATE, or PRIORITY valid to send
- * - Only HEADERS, RST_STREAM, or PRIORITY valid to receive
- */
- LWS_H2_STATE_OPEN,
- /*
- * Send RST_STREAM -> LWS_H2_STATE_CLOSED
- * Recv RST_STREAM -> LWS_H2_STATE_CLOSED
- * Send END_STREAM flag -> LWS_H2_STATE_HALF_CLOSED_LOCAL
- * Recv END_STREAM flag -> LWS_H2_STATE_HALF_CLOSED_REMOTE
- */
- LWS_H2_STATE_HALF_CLOSED_REMOTE,
- /*
- * Send RST_STREAM -> LWS_H2_STATE_CLOSED
- * Recv RST_STREAM -> LWS_H2_STATE_CLOSED
- * Send END_STREAM flag -> LWS_H2_STATE_CLOSED
- *
- * - Any frame valid to send
- * - Only WINDOW_UPDATE, PRIORITY, or RST_STREAM valid to receive
- */
- LWS_H2_STATE_HALF_CLOSED_LOCAL,
- /*
- * Send RST_STREAM -> LWS_H2_STATE_CLOSED
- * Recv RST_STREAM -> LWS_H2_STATE_CLOSED
- * Recv END_STREAM flag -> LWS_H2_STATE_CLOSED
- *
- * - Only WINDOW_UPDATE, PRIORITY, and RST_STREAM valid to send
- * - Any frame valid to receive
- */
- LWS_H2_STATE_CLOSED,
- /*
- * - Only PRIORITY, WINDOW_UPDATE (IGNORE) and RST_STREAM (IGNORE)
- * may be received
- *
- * - Only PRIORITY valid to send
- */
-};
-
-void
-lws_h2_state(struct lws *wsi, enum lws_h2_states s);
-
-#define LWS_H2_STREAM_ID_MASTER 0
-#define LWS_H2_SETTINGS_LEN 6
-#define LWS_H2_FLAG_SETTINGS_ACK 1
-
-enum http2_hpack_state {
- HPKS_TYPE,
-
- HPKS_IDX_EXT,
-
- HPKS_HLEN,
- HPKS_HLEN_EXT,
-
- HPKS_DATA,
-};
-
-/*
- * lws general parsimonious header strategy is only store values from known
- * headers, and refer to them by index.
- *
- * That means if we can't map the peer header name to one that lws knows, we
- * will drop the content but track the indexing with associated_lws_hdr_idx =
- * LWS_HPACK_IGNORE_ENTRY.
- */
-
-enum http2_hpack_type {
- HPKT_INDEXED_HDR_7, /* 1xxxxxxx: just "header field" */
- HPKT_INDEXED_HDR_6_VALUE_INCR, /* 01xxxxxx: NEW indexed hdr with value */
- HPKT_LITERAL_HDR_VALUE_INCR, /* 01000000: NEW literal hdr with value */
- HPKT_INDEXED_HDR_4_VALUE, /* 0000xxxx: indexed hdr with value */
- HPKT_INDEXED_HDR_4_VALUE_NEVER, /* 0001xxxx: indexed hdr with value NEVER NEW */
- HPKT_LITERAL_HDR_VALUE, /* 00000000: literal hdr with value */
- HPKT_LITERAL_HDR_VALUE_NEVER, /* 00010000: literal hdr with value NEVER NEW */
- HPKT_SIZE_5
-};
-
-#define LWS_HPACK_IGNORE_ENTRY 0xffff
-
-
-struct hpack_dt_entry {
- char *value; /* malloc'd */
- uint16_t value_len;
- uint16_t hdr_len; /* virtual, for accounting */
- uint16_t lws_hdr_idx; /* LWS_HPACK_IGNORE_ENTRY = IGNORE */
-};
-
-struct hpack_dynamic_table {
- struct hpack_dt_entry *entries; /* malloc'd */
- uint32_t virtual_payload_usage;
- uint32_t virtual_payload_max;
- uint16_t pos;
- uint16_t used_entries;
- uint16_t num_entries;
-};
-
-enum lws_h2_protocol_send_type {
- LWS_PPS_NONE,
- LWS_H2_PPS_MY_SETTINGS,
- LWS_H2_PPS_ACK_SETTINGS,
- LWS_H2_PPS_PONG,
- LWS_H2_PPS_GOAWAY,
- LWS_H2_PPS_RST_STREAM,
- LWS_H2_PPS_UPDATE_WINDOW,
-};
-
-struct lws_h2_protocol_send {
- struct lws_h2_protocol_send *next; /* linked list */
- enum lws_h2_protocol_send_type type;
-
- union uu {
- struct {
- char str[32];
- uint32_t highest_sid;
- uint32_t err;
- } ga;
- struct {
- uint32_t sid;
- uint32_t err;
- } rs;
- struct {
- uint8_t ping_payload[8];
- } ping;
- struct {
- uint32_t sid;
- uint32_t credit;
- } update_window;
- } u;
-};
-
-struct lws_h2_ghost_sid {
- struct lws_h2_ghost_sid *next;
- uint32_t sid;
-};
-
-/*
- * http/2 connection info that is only used by the root connection that has
- * the network connection.
- *
- * h2 tends to spawn many child connections from one network connection, so
- * it's necessary to make members only needed by the network connection
- * distinct and only malloc'd on network connections.
- *
- * There's only one HPACK parser per network connection.
- *
- * But there is an ah per logical child connection... the network connection
- * fills it but it belongs to the logical child.
- */
-struct lws_h2_netconn {
- struct http2_settings set;
- struct hpack_dynamic_table hpack_dyn_table;
- uint8_t ping_payload[8];
- uint8_t one_setting[LWS_H2_SETTINGS_LEN];
- char goaway_str[32]; /* for rx */
- struct lws *swsi;
- struct lws_h2_protocol_send *pps; /* linked list */
-
- enum http2_hpack_state hpack;
- enum http2_hpack_type hpack_type;
-
- unsigned int huff:1;
- unsigned int value:1;
- unsigned int unknown_header:1;
- unsigned int cont_exp:1;
- unsigned int cont_exp_headers:1;
- unsigned int we_told_goaway:1;
- unsigned int pad_length:1;
- unsigned int collected_priority:1;
- unsigned int is_first_header_char:1;
- unsigned int zero_huff_padding:1;
- unsigned int last_action_dyntable_resize:1;
-
- uint32_t hdr_idx;
- uint32_t hpack_len;
- uint32_t hpack_e_dep;
- uint32_t count;
- uint32_t preamble;
- uint32_t length;
- uint32_t sid;
- uint32_t inside;
- uint32_t highest_sid;
- uint32_t highest_sid_opened;
- uint32_t cont_exp_sid;
- uint32_t dep;
- uint32_t goaway_last_sid;
- uint32_t goaway_err;
- uint32_t hpack_hdr_len;
-
- uint16_t hpack_pos;
-
- uint8_t frame_state;
- uint8_t type;
- uint8_t flags;
- uint8_t padding;
- uint8_t weight_temp;
- uint8_t huff_pad;
- char first_hdr_char;
- uint8_t hpack_m;
- uint8_t ext_count;
-};
-
-struct _lws_h2_related {
-
- struct lws_h2_netconn *h2n; /* malloc'd for root net conn */
- struct lws *parent_wsi;
- struct lws *child_list;
- struct lws *sibling_list;
-
- char *pending_status_body;
-
- int tx_cr;
- int peer_tx_cr_est;
- unsigned int my_sid;
- unsigned int child_count;
- int my_priority;
- uint32_t dependent_on;
-
- unsigned int END_STREAM:1;
- unsigned int END_HEADERS:1;
- unsigned int send_END_STREAM:1;
- unsigned int GOING_AWAY;
- unsigned int requested_POLLOUT:1;
- unsigned int skint:1;
-
- uint16_t round_robin_POLLOUT;
- uint16_t count_POLLOUT_children;
-
- uint8_t h2_state; /* the RFC7540 state of the connection */
- uint8_t weight;
- uint8_t initialized;
-};
-
-#define HTTP2_IS_TOPLEVEL_WSI(wsi) (!wsi->h2.parent_wsi)
-
-int
-lws_h2_rst_stream(struct lws *wsi, uint32_t err, const char *reason);
-struct lws * lws_h2_get_nth_child(struct lws *wsi, int n);
-LWS_EXTERN void lws_h2_init(struct lws *wsi);
-LWS_EXTERN int
-lws_h2_settings(struct lws *nwsi, struct http2_settings *settings,
- unsigned char *buf, int len);
-LWS_EXTERN int
-lws_h2_parser(struct lws *wsi, unsigned char *in, lws_filepos_t inlen,
- lws_filepos_t *inused);
-LWS_EXTERN int
-lws_h2_do_pps_send(struct lws *wsi);
-LWS_EXTERN int
-lws_h2_frame_write(struct lws *wsi, int type, int flags, unsigned int sid,
- unsigned int len, unsigned char *buf);
-LWS_EXTERN struct lws *
-lws_h2_wsi_from_id(struct lws *wsi, unsigned int sid);
-LWS_EXTERN int
-lws_hpack_interpret(struct lws *wsi, unsigned char c);
-LWS_EXTERN int
-lws_add_http2_header_by_name(struct lws *wsi,
- const unsigned char *name,
- const unsigned char *value, int length,
- unsigned char **p, unsigned char *end);
-LWS_EXTERN int
-lws_add_http2_header_by_token(struct lws *wsi,
- enum lws_token_indexes token,
- const unsigned char *value, int length,
- unsigned char **p, unsigned char *end);
-LWS_EXTERN int
-lws_add_http2_header_status(struct lws *wsi,
- unsigned int code, unsigned char **p,
- unsigned char *end);
-LWS_EXTERN void
-lws_hpack_destroy_dynamic_header(struct lws *wsi);
-LWS_EXTERN int
-lws_hpack_dynamic_size(struct lws *wsi, int size);
-LWS_EXTERN int
-lws_h2_goaway(struct lws *wsi, uint32_t err, const char *reason);
-LWS_EXTERN int
-lws_h2_tx_cr_get(struct lws *wsi);
-LWS_EXTERN void
-lws_h2_tx_cr_consume(struct lws *wsi, int consumed);
-LWS_EXTERN int
-lws_hdr_extant(struct lws *wsi, enum lws_token_indexes h);
-LWS_EXTERN void
-lws_pps_schedule(struct lws *wsi, struct lws_h2_protocol_send *pss);
-
-LWS_EXTERN const struct http2_settings lws_h2_defaults;
-LWS_EXTERN int
-lws_h2_ws_handshake(struct lws *wsi);
-LWS_EXTERN int lws_h2_issue_preface(struct lws *wsi);
-LWS_EXTERN int
-lws_h2_client_handshake(struct lws *wsi);
-LWS_EXTERN struct lws *
-lws_wsi_h2_adopt(struct lws *parent_wsi, struct lws *wsi);
-int
-lws_handle_POLLOUT_event_h2(struct lws *wsi);
-int
-lws_read_h2(struct lws *wsi, unsigned char *buf, lws_filepos_t len);
-#include "core/private.h"
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "private-lib-core.h"
static int
lws_getaddrinfo46(struct lws *wsi, const char *ads, struct addrinfo **result)
--- /dev/null
+/*
+ * libwebsockets - lib/client/client.c
+ *
+ * Copyright (C) 2010-2018 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
+ */
+
+#include "private-lib-core.h"
+
+LWS_VISIBLE LWS_EXTERN void
+lws_client_http_body_pending(struct lws *wsi, int something_left_to_send)
+{
+ wsi->client_http_body_pending = !!something_left_to_send;
+}
+
+/*
+ * return self, or queued client wsi we are acting on behalf of
+ *
+ * That is the TAIL of the queue (new queue elements are added at the HEAD)
+ */
+
+struct lws *
+lws_client_wsi_effective(struct lws *wsi)
+{
+ struct lws_dll2 *tail = lws_dll2_get_tail(&wsi->dll2_cli_txn_queue_owner);
+
+ if (!wsi->transaction_from_pipeline_queue || !tail)
+ return wsi;
+
+ return lws_container_of(tail, struct lws, dll2_cli_txn_queue);
+}
+
+/*
+ * return self or the guy we are queued under
+ *
+ * REQUIRES VHOST LOCK HELD
+ */
+
+static struct lws *
+_lws_client_wsi_master(struct lws *wsi)
+{
+ struct lws_dll2_owner *o = wsi->dll2_cli_txn_queue.owner;
+
+ if (!o)
+ return wsi;
+
+ return lws_container_of(o, struct lws, dll2_cli_txn_queue_owner);
+}
+
+int
+lws_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd,
+ struct lws *wsi_conn)
+{
+ struct lws_context *context = wsi->context;
+ struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
+ char *p = (char *)&pt->serv_buf[0];
+ struct lws *w;
+#if defined(LWS_WITH_TLS)
+ char ebuf[128];
+#endif
+ const char *cce = NULL;
+#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
+ ssize_t len = 0;
+ unsigned char c;
+#endif
+ char *sb = p;
+ int n = 0;
+#if defined(LWS_WITH_SOCKS5)
+ int conn_mode = 0, pending_timeout = 0;
+#endif
+
+ if ((pollfd->revents & LWS_POLLOUT) &&
+ wsi->keepalive_active &&
+ wsi->dll2_cli_txn_queue_owner.head) {
+ struct lws *wfound = NULL;
+
+ lwsl_debug("%s: pollout HANDSHAKE2\n", __func__);
+
+ /*
+ * We have a transaction queued that wants to pipeline.
+ *
+ * We have to allow it to send headers strictly in the order
+ * that it was queued, ie, tail-first.
+ */
+ lws_vhost_lock(wsi->vhost);
+ lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
+ wsi->dll2_cli_txn_queue_owner.head) {
+ struct lws *w = lws_container_of(d, struct lws,
+ dll2_cli_txn_queue);
+
+ lwsl_debug("%s: %p states 0x%lx\n", __func__, w,
+ (unsigned long)w->wsistate);
+ if (lwsi_state(w) == LRS_H1C_ISSUE_HANDSHAKE2)
+ wfound = w;
+ } lws_end_foreach_dll_safe(d, d1);
+
+ if (wfound) {
+ /*
+ * pollfd has the master sockfd in it... we
+ * need to use that in HANDSHAKE2 to understand
+ * which wsi to actually write on
+ */
+ if (lws_client_socket_service(wfound, pollfd, wsi) < 0) {
+ /* closed */
+
+ lws_vhost_unlock(wsi->vhost);
+
+ return -1;
+ }
+
+ lws_callback_on_writable(wsi);
+ } else
+ lwsl_debug("%s: didn't find anything in txn q in HS2\n",
+ __func__);
+
+ lws_vhost_unlock(wsi->vhost);
+
+ return 0;
+ }
+
+ switch (lwsi_state(wsi)) {
+
+ case LRS_WAITING_CONNECT:
+
+ /*
+ * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
+ * timeout protection set in client-handshake.c
+ */
+
+ if (!lws_client_connect_2(wsi)) {
+ /* closed */
+ lwsl_client("closed\n");
+ return -1;
+ }
+
+ /* either still pending connection, or changed mode */
+ return 0;
+
+#if defined(LWS_WITH_SOCKS5)
+ /* SOCKS Greeting Reply */
+ case LRS_WAITING_SOCKS_GREETING_REPLY:
+ case LRS_WAITING_SOCKS_AUTH_REPLY:
+ case LRS_WAITING_SOCKS_CONNECT_REPLY:
+
+ /* handle proxy hung up on us */
+
+ if (pollfd->revents & LWS_POLLHUP) {
+ lwsl_warn("SOCKS connection %p (fd=%d) dead\n",
+ (void *)wsi, pollfd->fd);
+ cce = "socks conn dead";
+ goto bail3;
+ }
+
+ n = recv(wsi->desc.sockfd, sb, context->pt_serv_buf_size, 0);
+ if (n < 0) {
+ if (LWS_ERRNO == LWS_EAGAIN) {
+ lwsl_debug("SOCKS read EAGAIN, retrying\n");
+ return 0;
+ }
+ lwsl_err("ERROR reading from SOCKS socket\n");
+ cce = "socks recv fail";
+ goto bail3;
+ }
+
+ switch (lwsi_state(wsi)) {
+
+ case LRS_WAITING_SOCKS_GREETING_REPLY:
+ if (pt->serv_buf[0] != SOCKS_VERSION_5)
+ goto socks_reply_fail;
+
+ if (pt->serv_buf[1] == SOCKS_AUTH_NO_AUTH) {
+ lwsl_client("SOCKS GR: No Auth Method\n");
+ if (socks_generate_msg(wsi, SOCKS_MSG_CONNECT, &len))
+ goto socks_send_msg_fail;
+ conn_mode = LRS_WAITING_SOCKS_CONNECT_REPLY;
+ pending_timeout =
+ PENDING_TIMEOUT_AWAITING_SOCKS_CONNECT_REPLY;
+ goto socks_send;
+ }
+
+ if (pt->serv_buf[1] == SOCKS_AUTH_USERNAME_PASSWORD) {
+ lwsl_client("SOCKS GR: User/Pw Method\n");
+ if (socks_generate_msg(wsi,
+ SOCKS_MSG_USERNAME_PASSWORD,
+ &len))
+ goto socks_send_msg_fail;
+ conn_mode = LRS_WAITING_SOCKS_AUTH_REPLY;
+ pending_timeout =
+ PENDING_TIMEOUT_AWAITING_SOCKS_AUTH_REPLY;
+ goto socks_send;
+ }
+ goto socks_reply_fail;
+
+ case LRS_WAITING_SOCKS_AUTH_REPLY:
+ if (pt->serv_buf[0] != SOCKS_SUBNEGOTIATION_VERSION_1 ||
+ pt->serv_buf[1] !=
+ SOCKS_SUBNEGOTIATION_STATUS_SUCCESS)
+ goto socks_reply_fail;
+
+ lwsl_client("SOCKS password OK, sending connect\n");
+ if (socks_generate_msg(wsi, SOCKS_MSG_CONNECT, &len)) {
+socks_send_msg_fail:
+ *cce = "socks gen msg fail";
+ goto bail3;
+ }
+ conn_mode = LRS_WAITING_SOCKS_CONNECT_REPLY;
+ pending_timeout =
+ PENDING_TIMEOUT_AWAITING_SOCKS_CONNECT_REPLY;
+socks_send:
+ n = send(wsi->desc.sockfd, (char *)pt->serv_buf, len,
+ MSG_NOSIGNAL);
+ if (n < 0) {
+ lwsl_debug("ERROR writing to socks proxy\n");
+ cce = "socks write fail";
+ goto bail3;
+ }
+
+ lws_set_timeout(wsi, pending_timeout, AWAITING_TIMEOUT);
+ lwsi_set_state(wsi, conn_mode);
+ break;
+
+socks_reply_fail:
+ lwsl_notice("socks reply: v%d, err %d\n",
+ pt->serv_buf[0], pt->serv_buf[1]);
+ cce = "socks reply fail";
+ goto bail3;
+
+ case LRS_WAITING_SOCKS_CONNECT_REPLY:
+ if (pt->serv_buf[0] != SOCKS_VERSION_5 ||
+ pt->serv_buf[1] != SOCKS_REQUEST_REPLY_SUCCESS)
+ goto socks_reply_fail;
+
+ lwsl_client("socks connect OK\n");
+
+ /* free stash since we are done with it */
+ lws_client_stash_destroy(wsi);
+ if (lws_hdr_simple_create(wsi,
+ _WSI_TOKEN_CLIENT_PEER_ADDRESS,
+ wsi->vhost->socks_proxy_address)) {
+ cce = "socks connect fail";
+ goto bail3;
+ }
+
+ wsi->c_port = wsi->vhost->socks_proxy_port;
+
+ /* clear his proxy connection timeout */
+ lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
+ goto start_ws_handshake;
+ default:
+ break;
+ }
+ break;
+#endif
+
+ case LRS_WAITING_PROXY_REPLY:
+
+ /* handle proxy hung up on us */
+
+ if (pollfd->revents & LWS_POLLHUP) {
+
+ lwsl_warn("Proxy connection %p (fd=%d) dead\n",
+ (void *)wsi, pollfd->fd);
+
+ cce = "proxy conn dead";
+ goto bail3;
+ }
+
+ n = recv(wsi->desc.sockfd, sb, context->pt_serv_buf_size, 0);
+ if (n < 0) {
+ if (LWS_ERRNO == LWS_EAGAIN) {
+ lwsl_debug("Proxy read EAGAIN... retrying\n");
+ return 0;
+ }
+ lwsl_err("ERROR reading from proxy socket\n");
+ cce = "proxy read err";
+ goto bail3;
+ }
+
+ pt->serv_buf[13] = '\0';
+ if (strncmp(sb, "HTTP/1.0 200 ", 13) &&
+ strncmp(sb, "HTTP/1.1 200 ", 13)) {
+ lwsl_err("%s: ERROR proxy did not reply with h1\n",
+ __func__);
+ cce = "proxy not h1";
+ goto bail3;
+ }
+
+ /* clear his proxy connection timeout */
+
+ lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
+
+ /* fallthru */
+
+ case LRS_H1C_ISSUE_HANDSHAKE:
+
+ /*
+ * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
+ * timeout protection set in client-handshake.c
+ *
+ * take care of our lws_callback_on_writable
+ * happening at a time when there's no real connection yet
+ */
+#if defined(LWS_WITH_SOCKS5)
+start_ws_handshake:
+#endif
+ if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
+ return -1;
+
+#if defined(LWS_WITH_TLS)
+ /* we can retry this... just cook the SSL BIO the first time */
+
+ if ((wsi->tls.use_ssl & LCCSCF_USE_SSL) && !wsi->tls.ssl &&
+ lws_ssl_client_bio_create(wsi) < 0) {
+ cce = "bio_create failed";
+ goto bail3;
+ }
+
+ if (wsi->tls.use_ssl & LCCSCF_USE_SSL) {
+ n = lws_ssl_client_connect1(wsi);
+ if (!n)
+ return 0;
+ if (n < 0) {
+ cce = "lws_ssl_client_connect1 failed";
+ goto bail3;
+ }
+ } else
+ wsi->tls.ssl = NULL;
+
+ /* fallthru */
+
+ case LRS_WAITING_SSL:
+
+ if (wsi->tls.use_ssl & LCCSCF_USE_SSL) {
+ n = lws_ssl_client_connect2(wsi, ebuf, sizeof(ebuf));
+ if (!n)
+ return 0;
+ if (n < 0) {
+ cce = ebuf;
+ goto bail3;
+ }
+ } else
+ wsi->tls.ssl = NULL;
+#endif
+#if defined (LWS_WITH_HTTP2)
+ if (wsi->client_h2_alpn) {
+ /*
+ * We connected to the server and set up tls, and
+ * negotiated "h2".
+ *
+ * So this is it, we are an h2 master client connection
+ * now, not an h1 client connection.
+ */
+#if defined (LWS_WITH_TLS)
+ lws_tls_server_conn_alpn(wsi);
+#endif
+
+ /* send the H2 preface to legitimize the connection */
+ if (lws_h2_issue_preface(wsi)) {
+ cce = "error sending h2 preface";
+ goto bail3;
+ }
+
+ break;
+ }
+#endif
+ lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2);
+ lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND,
+ context->timeout_secs);
+
+ /* fallthru */
+
+ case LRS_H1C_ISSUE_HANDSHAKE2:
+ p = lws_generate_client_handshake(wsi, p);
+ if (p == NULL) {
+ if (wsi->role_ops == &role_ops_raw_skt ||
+ wsi->role_ops == &role_ops_raw_file)
+ return 0;
+
+ lwsl_err("Failed to generate handshake for client\n");
+ lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,
+ "chs");
+ return 0;
+ }
+
+ /* send our request to the server */
+ lws_latency_pre(context, wsi);
+
+ w = _lws_client_wsi_master(wsi);
+ lwsl_info("%s: HANDSHAKE2: %p: sending headers on %p "
+ "(wsistate 0x%lx 0x%lx), w sock %d, wsi sock %d\n",
+ __func__, wsi, w, (unsigned long)wsi->wsistate,
+ (unsigned long)w->wsistate, w->desc.sockfd,
+ wsi->desc.sockfd);
+
+ n = lws_ssl_capable_write(w, (unsigned char *)sb, (int)(p - sb));
+ lws_latency(context, wsi, "send lws_issue_raw", n,
+ n == p - sb);
+ switch (n) {
+ case LWS_SSL_CAPABLE_ERROR:
+ lwsl_debug("ERROR writing to client socket\n");
+ lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,
+ "cws");
+ return 0;
+ case LWS_SSL_CAPABLE_MORE_SERVICE:
+ lws_callback_on_writable(wsi);
+ break;
+ }
+
+ if (wsi->client_http_body_pending) {
+ lwsl_debug("body pending\n");
+ lwsi_set_state(wsi, LRS_ISSUE_HTTP_BODY);
+ lws_set_timeout(wsi,
+ PENDING_TIMEOUT_CLIENT_ISSUE_PAYLOAD,
+ context->timeout_secs);
+#if defined(LWS_WITH_HTTP_PROXY)
+ if (wsi->http.proxy_clientside)
+ lws_callback_on_writable(wsi);
+#endif
+ /* user code must ask for writable callback */
+ break;
+ }
+
+ lwsi_set_state(wsi, LRS_WAITING_SERVER_REPLY);
+ wsi->hdr_parsing_completed = 0;
+
+ if (lwsi_state(w) == LRS_IDLING) {
+ lwsi_set_state(w, LRS_WAITING_SERVER_REPLY);
+ w->hdr_parsing_completed = 0;
+#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
+ w->http.ah->parser_state = WSI_TOKEN_NAME_PART;
+ w->http.ah->lextable_pos = 0;
+#if defined(LWS_WITH_CUSTOM_HEADERS)
+ w->http.ah->unk_pos = 0;
+#endif
+ /* If we're (re)starting on hdr, need other implied init */
+ wsi->http.ah->ues = URIES_IDLE;
+#endif
+ }
+
+ lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
+ wsi->context->timeout_secs);
+
+ lws_callback_on_writable(w);
+
+ goto client_http_body_sent;
+
+ case LRS_ISSUE_HTTP_BODY:
+#if defined(LWS_WITH_HTTP_PROXY)
+ if (wsi->http.proxy_clientside) {
+ lws_callback_on_writable(wsi);
+ break;
+ }
+#endif
+ if (wsi->client_http_body_pending) {
+ //lws_set_timeout(wsi,
+ // PENDING_TIMEOUT_CLIENT_ISSUE_PAYLOAD,
+ // context->timeout_secs);
+ /* user code must ask for writable callback */
+ break;
+ }
+client_http_body_sent:
+#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
+ /* prepare ourselves to do the parsing */
+ wsi->http.ah->parser_state = WSI_TOKEN_NAME_PART;
+ wsi->http.ah->lextable_pos = 0;
+#if defined(LWS_WITH_CUSTOM_HEADERS)
+ wsi->http.ah->unk_pos = 0;
+#endif
+#endif
+ lwsi_set_state(wsi, LRS_WAITING_SERVER_REPLY);
+ lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
+ context->timeout_secs);
+ break;
+
+ case LRS_WAITING_SERVER_REPLY:
+ /*
+ * handle server hanging up on us...
+ * but if there is POLLIN waiting, handle that first
+ */
+ if ((pollfd->revents & (LWS_POLLIN | LWS_POLLHUP)) ==
+ LWS_POLLHUP) {
+
+ lwsl_debug("Server connection %p (fd=%d) dead\n",
+ (void *)wsi, pollfd->fd);
+ cce = "Peer hung up";
+ goto bail3;
+ }
+
+ if (!(pollfd->revents & LWS_POLLIN))
+ break;
+
+#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
+ /* interpret the server response
+ *
+ * HTTP/1.1 101 Switching Protocols
+ * Upgrade: websocket
+ * Connection: Upgrade
+ * Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo=
+ * Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC==
+ * Sec-WebSocket-Protocol: chat
+ *
+ * we have to take some care here to only take from the
+ * socket bytewise. The browser may (and has been seen to
+ * in the case that onopen() performs websocket traffic)
+ * coalesce both handshake response and websocket traffic
+ * in one packet, since at that point the connection is
+ * definitively ready from browser pov.
+ */
+ len = 1;
+ while (wsi->http.ah->parser_state != WSI_PARSING_COMPLETE &&
+ len > 0) {
+ int plen = 1;
+
+ n = lws_ssl_capable_read(wsi, &c, 1);
+ lws_latency(context, wsi, "send lws_issue_raw", n,
+ n == 1);
+ switch (n) {
+ case 0:
+ case LWS_SSL_CAPABLE_ERROR:
+ cce = "read failed";
+ goto bail3;
+ case LWS_SSL_CAPABLE_MORE_SERVICE:
+ return 0;
+ }
+
+ if (lws_parse(wsi, &c, &plen)) {
+ lwsl_warn("problems parsing header\n");
+ cce = "problems parsing header";
+ goto bail3;
+ }
+ }
+
+ /*
+ * hs may also be coming in multiple packets, there is a 5-sec
+ * libwebsocket timeout still active here too, so if parsing did
+ * not complete just wait for next packet coming in this state
+ */
+ if (wsi->http.ah->parser_state != WSI_PARSING_COMPLETE)
+ break;
+
+#endif
+
+ /*
+ * otherwise deal with the handshake. If there's any
+ * packet traffic already arrived we'll trigger poll() again
+ * right away and deal with it that way
+ */
+ return lws_client_interpret_server_handshake(wsi);
+
+bail3:
+ lwsl_info("closing conn at LWS_CONNMODE...SERVER_REPLY\n");
+ if (cce)
+ lwsl_info("reason: %s\n", cce);
+ lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce));
+
+ lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "cbail3");
+ return -1;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
+
+int LWS_WARN_UNUSED_RESULT
+lws_http_transaction_completed_client(struct lws *wsi)
+{
+ struct lws *wsi_eff = lws_client_wsi_effective(wsi);
+
+ lwsl_info("%s: wsi: %p, wsi_eff: %p (%s)\n", __func__, wsi, wsi_eff,
+ wsi_eff->protocol->name);
+
+ if (user_callback_handle_rxflow(wsi_eff->protocol->callback, wsi_eff,
+ LWS_CALLBACK_COMPLETED_CLIENT_HTTP,
+ wsi_eff->user_space, NULL, 0)) {
+ lwsl_debug("%s: Completed call returned nonzero (role 0x%lx)\n",
+ __func__, (unsigned long)lwsi_role(wsi_eff));
+ return -1;
+ }
+
+ /*
+ * Are we constitutionally capable of having a queue, ie, we are on
+ * the "active client connections" list?
+ *
+ * If not, that's it for us.
+ */
+
+ if (lws_dll2_is_detached(&wsi->dll_cli_active_conns))
+ return -1;
+
+ /* if this was a queued guy, close him and remove from queue */
+
+ if (wsi->transaction_from_pipeline_queue) {
+ lwsl_debug("closing queued wsi %p\n", wsi_eff);
+ /* so the close doesn't trigger a CCE */
+ wsi_eff->already_did_cce = 1;
+ __lws_close_free_wsi(wsi_eff,
+ LWS_CLOSE_STATUS_CLIENT_TRANSACTION_DONE,
+ "queued client done");
+ }
+
+ _lws_header_table_reset(wsi->http.ah);
+
+ /* after the first one, they can only be coming from the queue */
+ wsi->transaction_from_pipeline_queue = 1;
+
+ wsi->http.rx_content_length = 0;
+ wsi->hdr_parsing_completed = 0;
+
+ /* is there a new tail after removing that one? */
+ wsi_eff = lws_client_wsi_effective(wsi);
+
+ /*
+ * Do we have something pipelined waiting?
+ * it's OK if he hasn't managed to send his headers yet... he's next
+ * in line to do that...
+ */
+ if (wsi_eff == wsi) {
+ /*
+ * Nothing pipelined... we should hang around a bit
+ * in case something turns up...
+ */
+ lwsl_info("%s: nothing pipelined waiting\n", __func__);
+ lwsi_set_state(wsi, LRS_IDLING);
+
+ lws_set_timeout(wsi, PENDING_TIMEOUT_CLIENT_CONN_IDLE, 5);
+
+ return 0;
+ }
+
+ /*
+ * H1: we can serialize the queued guys into the same ah
+ * H2: everybody needs their own ah until their own STREAM_END
+ */
+
+ /* otherwise set ourselves up ready to go again */
+ lwsi_set_state(wsi, LRS_WAITING_SERVER_REPLY);
+
+ wsi->http.ah->parser_state = WSI_TOKEN_NAME_PART;
+ wsi->http.ah->lextable_pos = 0;
+#if defined(LWS_WITH_CUSTOM_HEADERS)
+ wsi->http.ah->unk_pos = 0;
+#endif
+
+ lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
+ wsi->context->timeout_secs);
+
+ /* If we're (re)starting on headers, need other implied init */
+ wsi->http.ah->ues = URIES_IDLE;
+
+ lwsl_info("%s: %p: new queued transaction as %p\n", __func__, wsi,
+ wsi_eff);
+ lws_callback_on_writable(wsi);
+
+ return 0;
+}
+
+LWS_VISIBLE LWS_EXTERN unsigned int
+lws_http_client_http_response(struct lws *_wsi)
+{
+ struct lws *wsi;
+ unsigned int resp;
+
+ if (_wsi->http.ah && _wsi->http.ah->http_response)
+ return _wsi->http.ah->http_response;
+
+ lws_vhost_lock(_wsi->vhost);
+ wsi = _lws_client_wsi_master(_wsi);
+ resp = wsi->http.ah->http_response;
+ lws_vhost_unlock(_wsi->vhost);
+
+ return resp;
+}
+#endif
+
+#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
+int
+lws_client_interpret_server_handshake(struct lws *wsi)
+{
+ int n, port = 0, ssl = 0;
+ int close_reason = LWS_CLOSE_STATUS_PROTOCOL_ERR;
+ const char *prot, *ads = NULL, *path, *cce = NULL;
+ struct allocated_headers *ah;
+ struct lws *w = lws_client_wsi_effective(wsi);
+ char *p, *q;
+ char new_path[300];
+
+ lws_client_stash_destroy(wsi);
+
+ ah = wsi->http.ah;
+ if (!wsi->do_ws) {
+ /* we are being an http client...
+ */
+#if defined(LWS_ROLE_H2)
+ if (wsi->client_h2_alpn || wsi->client_h2_substream) {
+ lwsl_debug("%s: %p: transitioning to h2 client\n",
+ __func__, wsi);
+ lws_role_transition(wsi, LWSIFR_CLIENT,
+ LRS_ESTABLISHED, &role_ops_h2);
+ } else
+#endif
+ {
+#if defined(LWS_ROLE_H1)
+ {
+ lwsl_debug("%s: %p: transitioning to h1 client\n",
+ __func__, wsi);
+ lws_role_transition(wsi, LWSIFR_CLIENT,
+ LRS_ESTABLISHED, &role_ops_h1);
+ }
+#else
+ return -1;
+#endif
+ }
+
+ wsi->http.ah = ah;
+ ah->http_response = 0;
+ }
+
+ /*
+ * well, what the server sent looked reasonable for syntax.
+ * Now let's confirm it sent all the necessary headers
+ *
+ * http (non-ws) client will expect something like this
+ *
+ * HTTP/1.0.200
+ * server:.libwebsockets
+ * content-type:.text/html
+ * content-length:.17703
+ * set-cookie:.test=LWS_1456736240_336776_COOKIE;Max-Age=360000
+ */
+
+ wsi->http.conn_type = HTTP_CONNECTION_KEEP_ALIVE;
+ if (!wsi->client_h2_substream) {
+ p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP);
+ if (wsi->do_ws && !p) {
+ lwsl_info("no URI\n");
+ cce = "HS: URI missing";
+ goto bail3;
+ }
+ if (!p) {
+ p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP1_0);
+ wsi->http.conn_type = HTTP_CONNECTION_CLOSE;
+ }
+ if (!p) {
+ cce = "HS: URI missing";
+ lwsl_info("no URI\n");
+ goto bail3;
+ }
+ } else {
+ p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_STATUS);
+ if (!p) {
+ cce = "HS: :status missing";
+ lwsl_info("no status\n");
+ goto bail3;
+ }
+ }
+ n = atoi(p);
+ if (ah)
+ ah->http_response = n;
+
+ if (
+#if defined(LWS_WITH_HTTP_PROXY)
+ !wsi->http.proxy_clientside &&
+#endif
+ (n == 301 || n == 302 || n == 303 || n == 307 || n == 308)) {
+ p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_LOCATION);
+ if (!p) {
+ cce = "HS: Redirect code but no Location";
+ goto bail3;
+ }
+
+ /* Relative reference absolute path */
+ if (p[0] == '/') {
+#if defined(LWS_WITH_TLS)
+ ssl = wsi->tls.use_ssl & LCCSCF_USE_SSL;
+#endif
+ ads = lws_hdr_simple_ptr(wsi,
+ _WSI_TOKEN_CLIENT_PEER_ADDRESS);
+ port = wsi->c_port;
+ /* +1 as lws_client_reset expects leading / omitted */
+ path = p + 1;
+ }
+ /* Absolute (Full) URI */
+ else if (strchr(p, ':')) {
+ if (lws_parse_uri(p, &prot, &ads, &port, &path)) {
+ cce = "HS: URI did not parse";
+ goto bail3;
+ }
+
+ if (!strcmp(prot, "wss") || !strcmp(prot, "https"))
+ ssl = 1;
+ }
+ /* Relative reference relative path */
+ else {
+ /* This doesn't try to calculate an absolute path,
+ * that will be left to the server */
+#if defined(LWS_WITH_TLS)
+ ssl = wsi->tls.use_ssl & LCCSCF_USE_SSL;
+#endif
+ ads = lws_hdr_simple_ptr(wsi,
+ _WSI_TOKEN_CLIENT_PEER_ADDRESS);
+ port = wsi->c_port;
+ /* +1 as lws_client_reset expects leading / omitted */
+ path = new_path + 1;
+ if (lws_hdr_simple_ptr(wsi,_WSI_TOKEN_CLIENT_URI))
+ lws_strncpy(new_path, lws_hdr_simple_ptr(wsi,
+ _WSI_TOKEN_CLIENT_URI), sizeof(new_path));
+ else {
+ new_path[0] = '/';
+ new_path[1] = '\0';
+ }
+ q = strrchr(new_path, '/');
+ if (q)
+ lws_strncpy(q + 1, p, sizeof(new_path) -
+ (q - new_path) - 1);
+ else
+ path = p;
+ }
+
+#if defined(LWS_WITH_TLS)
+ if ((wsi->tls.use_ssl & LCCSCF_USE_SSL) && !ssl) {
+ cce = "HS: Redirect attempted SSL downgrade";
+ goto bail3;
+ }
+#endif
+
+ if (!ads) /* make coverity happy */ {
+ cce = "no ads";
+ goto bail3;
+ }
+
+ if (!lws_client_reset(&wsi, ssl, ads, port, path, ads)) {
+ /* there are two ways to fail out with NULL return...
+ * simple, early problem where the wsi is intact, or
+ * we went through with the reconnect attempt and the
+ * wsi is already closed. In the latter case, the wsi
+ * has beet set to NULL additionally.
+ */
+ lwsl_err("Redirect failed\n");
+ cce = "HS: Redirect failed";
+ if (wsi)
+ goto bail3;
+
+ return 1;
+ }
+ return 0;
+ }
+
+ if (!wsi->do_ws) {
+
+ /* if h1 KA is allowed, enable the queued pipeline guys */
+
+ if (!wsi->client_h2_alpn && !wsi->client_h2_substream &&
+ w == wsi) { /* ie, coming to this for the first time */
+ if (wsi->http.conn_type == HTTP_CONNECTION_KEEP_ALIVE)
+ wsi->keepalive_active = 1;
+ else {
+ /*
+ * Ugh... now the main http connection has seen
+ * both sides, we learn the server doesn't
+ * support keepalive.
+ *
+ * That means any guys queued on us are going
+ * to have to be restarted from connect2 with
+ * their own connections.
+ */
+
+ /*
+ * stick around telling any new guys they can't
+ * pipeline to this server
+ */
+ wsi->keepalive_rejected = 1;
+
+ lws_vhost_lock(wsi->vhost);
+ lws_start_foreach_dll_safe(struct lws_dll2 *,
+ d, d1,
+ wsi->dll2_cli_txn_queue_owner.head) {
+ struct lws *ww = lws_container_of(d,
+ struct lws,
+ dll2_cli_txn_queue);
+
+ /* remove him from our queue */
+ lws_dll2_remove(&ww->dll2_cli_txn_queue);
+ /* give up on pipelining */
+ ww->client_pipeline = 0;
+
+ /* go back to "trying to connect" state */
+ lws_role_transition(ww, LWSIFR_CLIENT,
+ LRS_UNCONNECTED,
+#if defined(LWS_ROLE_H1)
+ &role_ops_h1);
+#else
+#if defined (LWS_ROLE_H2)
+ &role_ops_h2);
+#else
+ &role_ops_raw);
+#endif
+#endif
+ ww->user_space = NULL;
+ } lws_end_foreach_dll_safe(d, d1);
+ lws_vhost_unlock(wsi->vhost);
+ }
+ }
+
+#ifdef LWS_WITH_HTTP_PROXY
+ wsi->http.perform_rewrite = 0;
+ if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE)) {
+ if (!strncmp(lws_hdr_simple_ptr(wsi,
+ WSI_TOKEN_HTTP_CONTENT_TYPE),
+ "text/html", 9))
+ wsi->http.perform_rewrite = 0;
+ }
+#endif
+
+ /* allocate the per-connection user memory (if any) */
+ if (lws_ensure_user_space(wsi)) {
+ lwsl_err("Problem allocating wsi user mem\n");
+ cce = "HS: OOM";
+ goto bail2;
+ }
+
+ /* he may choose to send us stuff in chunked transfer-coding */
+ wsi->chunked = 0;
+ wsi->chunk_remaining = 0; /* ie, next thing is chunk size */
+ if (lws_hdr_total_length(wsi,
+ WSI_TOKEN_HTTP_TRANSFER_ENCODING)) {
+ wsi->chunked = !strcmp(lws_hdr_simple_ptr(wsi,
+ WSI_TOKEN_HTTP_TRANSFER_ENCODING),
+ "chunked");
+ /* first thing is hex, after payload there is crlf */
+ wsi->chunk_parser = ELCP_HEX;
+ }
+
+ if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
+ wsi->http.rx_content_length =
+ atoll(lws_hdr_simple_ptr(wsi,
+ WSI_TOKEN_HTTP_CONTENT_LENGTH));
+ lwsl_info("%s: incoming content length %llu\n",
+ __func__, (unsigned long long)
+ wsi->http.rx_content_length);
+ wsi->http.rx_content_remain =
+ wsi->http.rx_content_length;
+ } else /* can't do 1.1 without a content length or chunked */
+ if (!wsi->chunked)
+ wsi->http.conn_type = HTTP_CONNECTION_CLOSE;
+
+ /*
+ * we seem to be good to go, give client last chance to check
+ * headers and OK it
+ */
+ if (w->protocol->callback(w,
+ LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH,
+ w->user_space, NULL, 0)) {
+
+ cce = "HS: disallowed by client filter";
+ goto bail2;
+ }
+
+ /* clear his proxy connection timeout */
+ lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
+
+ wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
+
+ /* call him back to inform him he is up */
+ if (w->protocol->callback(w,
+ LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP,
+ w->user_space, NULL, 0)) {
+ cce = "HS: disallowed at ESTABLISHED";
+ goto bail3;
+ }
+
+ /*
+ * for pipelining, master needs to keep his ah... guys who
+ * queued on him can drop it now though.
+ */
+
+ if (w != wsi)
+ /* free up parsing allocations for queued guy */
+ lws_header_table_detach(w, 0);
+
+ lwsl_info("%s: client connection up\n", __func__);
+
+ /*
+ * Did we get a response from the server with an explicit
+ * content-length of zero? If so, this transaction is already
+ * completed at the end of the header processing...
+ */
+ if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH) &&
+ !wsi->http.rx_content_length)
+ return !!lws_http_transaction_completed_client(wsi);
+
+ return 0;
+ }
+
+#if defined(LWS_ROLE_WS)
+ switch (lws_client_ws_upgrade(wsi, &cce)) {
+ case 2:
+ goto bail2;
+ case 3:
+ goto bail3;
+ }
+
+ return 0;
+#endif
+
+bail3:
+ close_reason = LWS_CLOSE_STATUS_NOSTATUS;
+
+bail2:
+ if (wsi->protocol) {
+ n = 0;
+ if (cce)
+ n = (int)strlen(cce);
+
+ lws_inform_client_conn_fail(wsi, (void *)cce, (unsigned int)n);
+ }
+
+ lwsl_info("closing connection (prot %s) "
+ "due to bail2 connection error: %s\n", wsi->protocol ?
+ wsi->protocol->name : "unknown", cce);
+
+ /* closing will free up his parsing allocations */
+ lws_close_free_wsi(wsi, close_reason, "c hs interp");
+
+ return 1;
+}
+#endif
+
+char *
+lws_generate_client_handshake(struct lws *wsi, char *pkt)
+{
+ char *p = pkt;
+ const char *meth;
+ const char *pp = lws_hdr_simple_ptr(wsi,
+ _WSI_TOKEN_CLIENT_SENT_PROTOCOLS);
+
+ meth = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_METHOD);
+ if (!meth) {
+ meth = "GET";
+ wsi->do_ws = 1;
+ } else {
+ wsi->do_ws = 0;
+ }
+
+ if (!strcmp(meth, "RAW")) {
+ lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
+ lwsl_notice("client transition to raw\n");
+
+ if (pp) {
+ const struct lws_protocols *pr;
+
+ pr = lws_vhost_name_to_protocol(wsi->vhost, pp);
+
+ if (!pr) {
+ lwsl_err("protocol %s not enabled on vhost\n",
+ pp);
+ return NULL;
+ }
+
+ lws_bind_protocol(wsi, pr, __func__);
+ }
+
+ if ((wsi->protocol->callback)(wsi, LWS_CALLBACK_RAW_ADOPT,
+ wsi->user_space, NULL, 0))
+ return NULL;
+
+ lws_role_transition(wsi, LWSIFR_CLIENT, LRS_ESTABLISHED,
+ &role_ops_raw_skt);
+ lws_header_table_detach(wsi, 1);
+
+ return NULL;
+ }
+
+ /*
+ * 04 example client handshake
+ *
+ * GET /chat HTTP/1.1
+ * Host: server.example.com
+ * Upgrade: websocket
+ * Connection: Upgrade
+ * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
+ * Sec-WebSocket-Origin: http://example.com
+ * Sec-WebSocket-Protocol: chat, superchat
+ * Sec-WebSocket-Version: 4
+ */
+
+ p += lws_snprintf(p, 2048, "%s %s HTTP/1.1\x0d\x0a", meth,
+ lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI));
+
+ p += lws_snprintf(p, 64, "Pragma: no-cache\x0d\x0a"
+ "Cache-Control: no-cache\x0d\x0a");
+
+ p += lws_snprintf(p, 128, "Host: %s\x0d\x0a",
+ lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST));
+
+ if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN)) {
+ if (lws_check_opt(wsi->context->options,
+ LWS_SERVER_OPTION_JUST_USE_RAW_ORIGIN))
+ p += lws_snprintf(p, 128, "Origin: %s\x0d\x0a",
+ lws_hdr_simple_ptr(wsi,
+ _WSI_TOKEN_CLIENT_ORIGIN));
+ else
+ p += lws_snprintf(p, 128, "Origin: http://%s\x0d\x0a",
+ lws_hdr_simple_ptr(wsi,
+ _WSI_TOKEN_CLIENT_ORIGIN));
+ }
+
+#if defined(LWS_WITH_HTTP_PROXY)
+ if (wsi->parent &&
+ lws_hdr_total_length(wsi->parent, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
+ p += lws_snprintf(p, 128, "Content-Length: %s\x0d\x0a",
+ lws_hdr_simple_ptr(wsi->parent, WSI_TOKEN_HTTP_CONTENT_LENGTH));
+ if (atoi(lws_hdr_simple_ptr(wsi->parent, WSI_TOKEN_HTTP_CONTENT_LENGTH)))
+ wsi->client_http_body_pending = 1;
+ }
+ if (wsi->parent &&
+ lws_hdr_total_length(wsi->parent, WSI_TOKEN_HTTP_AUTHORIZATION)) {
+ p += lws_snprintf(p, 128, "Authorization: %s\x0d\x0a",
+ lws_hdr_simple_ptr(wsi->parent, WSI_TOKEN_HTTP_AUTHORIZATION));
+ }
+ if (wsi->parent &&
+ lws_hdr_total_length(wsi->parent, WSI_TOKEN_HTTP_CONTENT_TYPE)) {
+ p += lws_snprintf(p, 128, "Content-Type: %s\x0d\x0a",
+ lws_hdr_simple_ptr(wsi->parent, WSI_TOKEN_HTTP_CONTENT_TYPE));
+ }
+#endif
+
+#if defined(LWS_ROLE_WS)
+ if (wsi->do_ws) {
+ const char *conn1 = "";
+ // if (!wsi->client_pipeline)
+ // conn1 = "close, ";
+ p = lws_generate_client_ws_handshake(wsi, p, conn1);
+ } else
+#endif
+ {
+ if (!wsi->client_pipeline)
+ p += lws_snprintf(p, 64, "connection: close\x0d\x0a");
+ }
+
+ /* give userland a chance to append, eg, cookies */
+
+ if (wsi->protocol->callback(wsi,
+ LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
+ wsi->user_space, &p,
+ (pkt + wsi->context->pt_serv_buf_size) - p - 12))
+ return NULL;
+
+ p += lws_snprintf(p, 4, "\x0d\x0a");
+
+ // puts(pkt);
+
+ return p;
+}
+
+#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
+
+LWS_VISIBLE int
+lws_http_client_read(struct lws *wsi, char **buf, int *len)
+{
+ int rlen, n;
+
+ rlen = lws_ssl_capable_read(wsi, (unsigned char *)*buf, *len);
+ *len = 0;
+
+ // lwsl_notice("%s: rlen %d\n", __func__, rlen);
+
+ /* allow the source to signal he has data again next time */
+ if (lws_change_pollfd(wsi, 0, LWS_POLLIN))
+ return -1;
+
+ if (rlen == LWS_SSL_CAPABLE_ERROR) {
+ lwsl_debug("%s: SSL capable error\n", __func__);
+ return -1;
+ }
+
+ if (rlen <= 0)
+ return 0;
+
+ *len = rlen;
+ wsi->client_rx_avail = 0;
+
+ /*
+ * server may insist on transfer-encoding: chunked,
+ * so http client must deal with it
+ */
+spin_chunks:
+ while (wsi->chunked && (wsi->chunk_parser != ELCP_CONTENT) && *len) {
+ switch (wsi->chunk_parser) {
+ case ELCP_HEX:
+ if ((*buf)[0] == '\x0d') {
+ wsi->chunk_parser = ELCP_CR;
+ break;
+ }
+ n = char_to_hex((*buf)[0]);
+ if (n < 0) {
+ lwsl_info("%s: chunking failure\n", __func__);
+ return -1;
+ }
+ wsi->chunk_remaining <<= 4;
+ wsi->chunk_remaining |= n;
+ break;
+ case ELCP_CR:
+ if ((*buf)[0] != '\x0a') {
+ lwsl_info("%s: chunking failure\n", __func__);
+ return -1;
+ }
+ wsi->chunk_parser = ELCP_CONTENT;
+ lwsl_info("chunk %d\n", wsi->chunk_remaining);
+ if (wsi->chunk_remaining)
+ break;
+ lwsl_info("final chunk\n");
+ goto completed;
+
+ case ELCP_CONTENT:
+ break;
+
+ case ELCP_POST_CR:
+ if ((*buf)[0] != '\x0d') {
+ lwsl_info("%s: chunking failure\n", __func__);
+
+ return -1;
+ }
+
+ wsi->chunk_parser = ELCP_POST_LF;
+ break;
+
+ case ELCP_POST_LF:
+ if ((*buf)[0] != '\x0a') {
+ lwsl_info("%s: chunking failure\n", __func__);
+
+ return -1;
+ }
+
+ wsi->chunk_parser = ELCP_HEX;
+ wsi->chunk_remaining = 0;
+ break;
+ }
+ (*buf)++;
+ (*len)--;
+ }
+
+ if (wsi->chunked && !wsi->chunk_remaining)
+ return 0;
+
+ if (wsi->http.rx_content_remain &&
+ wsi->http.rx_content_remain < (unsigned int)*len)
+ n = (int)wsi->http.rx_content_remain;
+ else
+ n = *len;
+
+ if (wsi->chunked && wsi->chunk_remaining &&
+ wsi->chunk_remaining < n)
+ n = wsi->chunk_remaining;
+
+#if defined(LWS_WITH_HTTP_PROXY) && defined(LWS_WITH_HUBBUB)
+ /* hubbub */
+ if (wsi->http.perform_rewrite)
+ lws_rewrite_parse(wsi->http.rw, (unsigned char *)*buf, n);
+ else
+#endif
+ {
+ struct lws *wsi_eff = lws_client_wsi_effective(wsi);
+
+ if (
+#if defined(LWS_WITH_HTTP_PROXY)
+ !wsi_eff->protocol_bind_balance ==
+ !!wsi_eff->http.proxy_clientside &&
+#else
+ !!wsi_eff->protocol_bind_balance &&
+#endif
+ user_callback_handle_rxflow(wsi_eff->protocol->callback,
+ wsi_eff, LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ,
+ wsi_eff->user_space, *buf, n)) {
+ lwsl_info("%s: RECEIVE_CLIENT_HTTP_READ returned -1\n",
+ __func__);
+
+ return -1;
+ }
+ }
+
+ if (wsi->chunked && wsi->chunk_remaining) {
+ (*buf) += n;
+ wsi->chunk_remaining -= n;
+ *len -= n;
+ }
+
+ if (wsi->chunked && !wsi->chunk_remaining)
+ wsi->chunk_parser = ELCP_POST_CR;
+
+ if (wsi->chunked && *len)
+ goto spin_chunks;
+
+ if (wsi->chunked)
+ return 0;
+
+ /* if we know the content length, decrement the content remaining */
+ if (wsi->http.rx_content_length > 0)
+ wsi->http.rx_content_remain -= n;
+
+ // lwsl_notice("rx_content_remain %lld, rx_content_length %lld\n",
+ // wsi->http.rx_content_remain, wsi->http.rx_content_length);
+
+ if (wsi->http.rx_content_remain || !wsi->http.rx_content_length)
+ return 0;
+
+completed:
+
+ if (lws_http_transaction_completed_client(wsi)) {
+ lwsl_notice("%s: transaction completed says -1\n", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+#endif
+++ /dev/null
-/*
- * libwebsockets - lib/client/client.c
- *
- * Copyright (C) 2010-2018 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
- */
-
-#include "core/private.h"
-
-LWS_VISIBLE LWS_EXTERN void
-lws_client_http_body_pending(struct lws *wsi, int something_left_to_send)
-{
- wsi->client_http_body_pending = !!something_left_to_send;
-}
-
-/*
- * return self, or queued client wsi we are acting on behalf of
- *
- * That is the TAIL of the queue (new queue elements are added at the HEAD)
- */
-
-struct lws *
-lws_client_wsi_effective(struct lws *wsi)
-{
- struct lws_dll2 *tail = lws_dll2_get_tail(&wsi->dll2_cli_txn_queue_owner);
-
- if (!wsi->transaction_from_pipeline_queue || !tail)
- return wsi;
-
- return lws_container_of(tail, struct lws, dll2_cli_txn_queue);
-}
-
-/*
- * return self or the guy we are queued under
- *
- * REQUIRES VHOST LOCK HELD
- */
-
-static struct lws *
-_lws_client_wsi_master(struct lws *wsi)
-{
- struct lws_dll2_owner *o = wsi->dll2_cli_txn_queue.owner;
-
- if (!o)
- return wsi;
-
- return lws_container_of(o, struct lws, dll2_cli_txn_queue_owner);
-}
-
-int
-lws_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd,
- struct lws *wsi_conn)
-{
- struct lws_context *context = wsi->context;
- struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
- char *p = (char *)&pt->serv_buf[0];
- struct lws *w;
-#if defined(LWS_WITH_TLS)
- char ebuf[128];
-#endif
- const char *cce = NULL;
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- ssize_t len = 0;
- unsigned char c;
-#endif
- char *sb = p;
- int n = 0;
-#if defined(LWS_WITH_SOCKS5)
- int conn_mode = 0, pending_timeout = 0;
-#endif
-
- if ((pollfd->revents & LWS_POLLOUT) &&
- wsi->keepalive_active &&
- wsi->dll2_cli_txn_queue_owner.head) {
- struct lws *wfound = NULL;
-
- lwsl_debug("%s: pollout HANDSHAKE2\n", __func__);
-
- /*
- * We have a transaction queued that wants to pipeline.
- *
- * We have to allow it to send headers strictly in the order
- * that it was queued, ie, tail-first.
- */
- lws_vhost_lock(wsi->vhost);
- lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
- wsi->dll2_cli_txn_queue_owner.head) {
- struct lws *w = lws_container_of(d, struct lws,
- dll2_cli_txn_queue);
-
- lwsl_debug("%s: %p states 0x%lx\n", __func__, w,
- (unsigned long)w->wsistate);
- if (lwsi_state(w) == LRS_H1C_ISSUE_HANDSHAKE2)
- wfound = w;
- } lws_end_foreach_dll_safe(d, d1);
-
- if (wfound) {
- /*
- * pollfd has the master sockfd in it... we
- * need to use that in HANDSHAKE2 to understand
- * which wsi to actually write on
- */
- if (lws_client_socket_service(wfound, pollfd, wsi) < 0) {
- /* closed */
-
- lws_vhost_unlock(wsi->vhost);
-
- return -1;
- }
-
- lws_callback_on_writable(wsi);
- } else
- lwsl_debug("%s: didn't find anything in txn q in HS2\n",
- __func__);
-
- lws_vhost_unlock(wsi->vhost);
-
- return 0;
- }
-
- switch (lwsi_state(wsi)) {
-
- case LRS_WAITING_CONNECT:
-
- /*
- * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
- * timeout protection set in client-handshake.c
- */
-
- if (!lws_client_connect_2(wsi)) {
- /* closed */
- lwsl_client("closed\n");
- return -1;
- }
-
- /* either still pending connection, or changed mode */
- return 0;
-
-#if defined(LWS_WITH_SOCKS5)
- /* SOCKS Greeting Reply */
- case LRS_WAITING_SOCKS_GREETING_REPLY:
- case LRS_WAITING_SOCKS_AUTH_REPLY:
- case LRS_WAITING_SOCKS_CONNECT_REPLY:
-
- /* handle proxy hung up on us */
-
- if (pollfd->revents & LWS_POLLHUP) {
- lwsl_warn("SOCKS connection %p (fd=%d) dead\n",
- (void *)wsi, pollfd->fd);
- cce = "socks conn dead";
- goto bail3;
- }
-
- n = recv(wsi->desc.sockfd, sb, context->pt_serv_buf_size, 0);
- if (n < 0) {
- if (LWS_ERRNO == LWS_EAGAIN) {
- lwsl_debug("SOCKS read EAGAIN, retrying\n");
- return 0;
- }
- lwsl_err("ERROR reading from SOCKS socket\n");
- cce = "socks recv fail";
- goto bail3;
- }
-
- switch (lwsi_state(wsi)) {
-
- case LRS_WAITING_SOCKS_GREETING_REPLY:
- if (pt->serv_buf[0] != SOCKS_VERSION_5)
- goto socks_reply_fail;
-
- if (pt->serv_buf[1] == SOCKS_AUTH_NO_AUTH) {
- lwsl_client("SOCKS GR: No Auth Method\n");
- if (socks_generate_msg(wsi, SOCKS_MSG_CONNECT, &len))
- goto socks_send_msg_fail;
- conn_mode = LRS_WAITING_SOCKS_CONNECT_REPLY;
- pending_timeout =
- PENDING_TIMEOUT_AWAITING_SOCKS_CONNECT_REPLY;
- goto socks_send;
- }
-
- if (pt->serv_buf[1] == SOCKS_AUTH_USERNAME_PASSWORD) {
- lwsl_client("SOCKS GR: User/Pw Method\n");
- if (socks_generate_msg(wsi,
- SOCKS_MSG_USERNAME_PASSWORD,
- &len))
- goto socks_send_msg_fail;
- conn_mode = LRS_WAITING_SOCKS_AUTH_REPLY;
- pending_timeout =
- PENDING_TIMEOUT_AWAITING_SOCKS_AUTH_REPLY;
- goto socks_send;
- }
- goto socks_reply_fail;
-
- case LRS_WAITING_SOCKS_AUTH_REPLY:
- if (pt->serv_buf[0] != SOCKS_SUBNEGOTIATION_VERSION_1 ||
- pt->serv_buf[1] !=
- SOCKS_SUBNEGOTIATION_STATUS_SUCCESS)
- goto socks_reply_fail;
-
- lwsl_client("SOCKS password OK, sending connect\n");
- if (socks_generate_msg(wsi, SOCKS_MSG_CONNECT, &len)) {
-socks_send_msg_fail:
- *cce = "socks gen msg fail";
- goto bail3;
- }
- conn_mode = LRS_WAITING_SOCKS_CONNECT_REPLY;
- pending_timeout =
- PENDING_TIMEOUT_AWAITING_SOCKS_CONNECT_REPLY;
-socks_send:
- n = send(wsi->desc.sockfd, (char *)pt->serv_buf, len,
- MSG_NOSIGNAL);
- if (n < 0) {
- lwsl_debug("ERROR writing to socks proxy\n");
- cce = "socks write fail";
- goto bail3;
- }
-
- lws_set_timeout(wsi, pending_timeout, AWAITING_TIMEOUT);
- lwsi_set_state(wsi, conn_mode);
- break;
-
-socks_reply_fail:
- lwsl_notice("socks reply: v%d, err %d\n",
- pt->serv_buf[0], pt->serv_buf[1]);
- cce = "socks reply fail";
- goto bail3;
-
- case LRS_WAITING_SOCKS_CONNECT_REPLY:
- if (pt->serv_buf[0] != SOCKS_VERSION_5 ||
- pt->serv_buf[1] != SOCKS_REQUEST_REPLY_SUCCESS)
- goto socks_reply_fail;
-
- lwsl_client("socks connect OK\n");
-
- /* free stash since we are done with it */
- lws_client_stash_destroy(wsi);
- if (lws_hdr_simple_create(wsi,
- _WSI_TOKEN_CLIENT_PEER_ADDRESS,
- wsi->vhost->socks_proxy_address)) {
- cce = "socks connect fail";
- goto bail3;
- }
-
- wsi->c_port = wsi->vhost->socks_proxy_port;
-
- /* clear his proxy connection timeout */
- lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
- goto start_ws_handshake;
- default:
- break;
- }
- break;
-#endif
-
- case LRS_WAITING_PROXY_REPLY:
-
- /* handle proxy hung up on us */
-
- if (pollfd->revents & LWS_POLLHUP) {
-
- lwsl_warn("Proxy connection %p (fd=%d) dead\n",
- (void *)wsi, pollfd->fd);
-
- cce = "proxy conn dead";
- goto bail3;
- }
-
- n = recv(wsi->desc.sockfd, sb, context->pt_serv_buf_size, 0);
- if (n < 0) {
- if (LWS_ERRNO == LWS_EAGAIN) {
- lwsl_debug("Proxy read EAGAIN... retrying\n");
- return 0;
- }
- lwsl_err("ERROR reading from proxy socket\n");
- cce = "proxy read err";
- goto bail3;
- }
-
- pt->serv_buf[13] = '\0';
- if (strncmp(sb, "HTTP/1.0 200 ", 13) &&
- strncmp(sb, "HTTP/1.1 200 ", 13)) {
- lwsl_err("%s: ERROR proxy did not reply with h1\n",
- __func__);
- cce = "proxy not h1";
- goto bail3;
- }
-
- /* clear his proxy connection timeout */
-
- lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
-
- /* fallthru */
-
- case LRS_H1C_ISSUE_HANDSHAKE:
-
- /*
- * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
- * timeout protection set in client-handshake.c
- *
- * take care of our lws_callback_on_writable
- * happening at a time when there's no real connection yet
- */
-#if defined(LWS_WITH_SOCKS5)
-start_ws_handshake:
-#endif
- if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
- return -1;
-
-#if defined(LWS_WITH_TLS)
- /* we can retry this... just cook the SSL BIO the first time */
-
- if ((wsi->tls.use_ssl & LCCSCF_USE_SSL) && !wsi->tls.ssl &&
- lws_ssl_client_bio_create(wsi) < 0) {
- cce = "bio_create failed";
- goto bail3;
- }
-
- if (wsi->tls.use_ssl & LCCSCF_USE_SSL) {
- n = lws_ssl_client_connect1(wsi);
- if (!n)
- return 0;
- if (n < 0) {
- cce = "lws_ssl_client_connect1 failed";
- goto bail3;
- }
- } else
- wsi->tls.ssl = NULL;
-
- /* fallthru */
-
- case LRS_WAITING_SSL:
-
- if (wsi->tls.use_ssl & LCCSCF_USE_SSL) {
- n = lws_ssl_client_connect2(wsi, ebuf, sizeof(ebuf));
- if (!n)
- return 0;
- if (n < 0) {
- cce = ebuf;
- goto bail3;
- }
- } else
- wsi->tls.ssl = NULL;
-#endif
-#if defined (LWS_WITH_HTTP2)
- if (wsi->client_h2_alpn) {
- /*
- * We connected to the server and set up tls, and
- * negotiated "h2".
- *
- * So this is it, we are an h2 master client connection
- * now, not an h1 client connection.
- */
-#if defined (LWS_WITH_TLS)
- lws_tls_server_conn_alpn(wsi);
-#endif
-
- /* send the H2 preface to legitimize the connection */
- if (lws_h2_issue_preface(wsi)) {
- cce = "error sending h2 preface";
- goto bail3;
- }
-
- break;
- }
-#endif
- lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2);
- lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND,
- context->timeout_secs);
-
- /* fallthru */
-
- case LRS_H1C_ISSUE_HANDSHAKE2:
- p = lws_generate_client_handshake(wsi, p);
- if (p == NULL) {
- if (wsi->role_ops == &role_ops_raw_skt ||
- wsi->role_ops == &role_ops_raw_file)
- return 0;
-
- lwsl_err("Failed to generate handshake for client\n");
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,
- "chs");
- return 0;
- }
-
- /* send our request to the server */
- lws_latency_pre(context, wsi);
-
- w = _lws_client_wsi_master(wsi);
- lwsl_info("%s: HANDSHAKE2: %p: sending headers on %p "
- "(wsistate 0x%lx 0x%lx), w sock %d, wsi sock %d\n",
- __func__, wsi, w, (unsigned long)wsi->wsistate,
- (unsigned long)w->wsistate, w->desc.sockfd,
- wsi->desc.sockfd);
-
- n = lws_ssl_capable_write(w, (unsigned char *)sb, (int)(p - sb));
- lws_latency(context, wsi, "send lws_issue_raw", n,
- n == p - sb);
- switch (n) {
- case LWS_SSL_CAPABLE_ERROR:
- lwsl_debug("ERROR writing to client socket\n");
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,
- "cws");
- return 0;
- case LWS_SSL_CAPABLE_MORE_SERVICE:
- lws_callback_on_writable(wsi);
- break;
- }
-
- if (wsi->client_http_body_pending) {
- lwsl_debug("body pending\n");
- lwsi_set_state(wsi, LRS_ISSUE_HTTP_BODY);
- lws_set_timeout(wsi,
- PENDING_TIMEOUT_CLIENT_ISSUE_PAYLOAD,
- context->timeout_secs);
-#if defined(LWS_WITH_HTTP_PROXY)
- if (wsi->http.proxy_clientside)
- lws_callback_on_writable(wsi);
-#endif
- /* user code must ask for writable callback */
- break;
- }
-
- lwsi_set_state(wsi, LRS_WAITING_SERVER_REPLY);
- wsi->hdr_parsing_completed = 0;
-
- if (lwsi_state(w) == LRS_IDLING) {
- lwsi_set_state(w, LRS_WAITING_SERVER_REPLY);
- w->hdr_parsing_completed = 0;
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- w->http.ah->parser_state = WSI_TOKEN_NAME_PART;
- w->http.ah->lextable_pos = 0;
-#if defined(LWS_WITH_CUSTOM_HEADERS)
- w->http.ah->unk_pos = 0;
-#endif
- /* If we're (re)starting on hdr, need other implied init */
- wsi->http.ah->ues = URIES_IDLE;
-#endif
- }
-
- lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
- wsi->context->timeout_secs);
-
- lws_callback_on_writable(w);
-
- goto client_http_body_sent;
-
- case LRS_ISSUE_HTTP_BODY:
-#if defined(LWS_WITH_HTTP_PROXY)
- if (wsi->http.proxy_clientside) {
- lws_callback_on_writable(wsi);
- break;
- }
-#endif
- if (wsi->client_http_body_pending) {
- //lws_set_timeout(wsi,
- // PENDING_TIMEOUT_CLIENT_ISSUE_PAYLOAD,
- // context->timeout_secs);
- /* user code must ask for writable callback */
- break;
- }
-client_http_body_sent:
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- /* prepare ourselves to do the parsing */
- wsi->http.ah->parser_state = WSI_TOKEN_NAME_PART;
- wsi->http.ah->lextable_pos = 0;
-#if defined(LWS_WITH_CUSTOM_HEADERS)
- wsi->http.ah->unk_pos = 0;
-#endif
-#endif
- lwsi_set_state(wsi, LRS_WAITING_SERVER_REPLY);
- lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
- context->timeout_secs);
- break;
-
- case LRS_WAITING_SERVER_REPLY:
- /*
- * handle server hanging up on us...
- * but if there is POLLIN waiting, handle that first
- */
- if ((pollfd->revents & (LWS_POLLIN | LWS_POLLHUP)) ==
- LWS_POLLHUP) {
-
- lwsl_debug("Server connection %p (fd=%d) dead\n",
- (void *)wsi, pollfd->fd);
- cce = "Peer hung up";
- goto bail3;
- }
-
- if (!(pollfd->revents & LWS_POLLIN))
- break;
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- /* interpret the server response
- *
- * HTTP/1.1 101 Switching Protocols
- * Upgrade: websocket
- * Connection: Upgrade
- * Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo=
- * Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC==
- * Sec-WebSocket-Protocol: chat
- *
- * we have to take some care here to only take from the
- * socket bytewise. The browser may (and has been seen to
- * in the case that onopen() performs websocket traffic)
- * coalesce both handshake response and websocket traffic
- * in one packet, since at that point the connection is
- * definitively ready from browser pov.
- */
- len = 1;
- while (wsi->http.ah->parser_state != WSI_PARSING_COMPLETE &&
- len > 0) {
- int plen = 1;
-
- n = lws_ssl_capable_read(wsi, &c, 1);
- lws_latency(context, wsi, "send lws_issue_raw", n,
- n == 1);
- switch (n) {
- case 0:
- case LWS_SSL_CAPABLE_ERROR:
- cce = "read failed";
- goto bail3;
- case LWS_SSL_CAPABLE_MORE_SERVICE:
- return 0;
- }
-
- if (lws_parse(wsi, &c, &plen)) {
- lwsl_warn("problems parsing header\n");
- cce = "problems parsing header";
- goto bail3;
- }
- }
-
- /*
- * hs may also be coming in multiple packets, there is a 5-sec
- * libwebsocket timeout still active here too, so if parsing did
- * not complete just wait for next packet coming in this state
- */
- if (wsi->http.ah->parser_state != WSI_PARSING_COMPLETE)
- break;
-
-#endif
-
- /*
- * otherwise deal with the handshake. If there's any
- * packet traffic already arrived we'll trigger poll() again
- * right away and deal with it that way
- */
- return lws_client_interpret_server_handshake(wsi);
-
-bail3:
- lwsl_info("closing conn at LWS_CONNMODE...SERVER_REPLY\n");
- if (cce)
- lwsl_info("reason: %s\n", cce);
- lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce));
-
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "cbail3");
- return -1;
-
- default:
- break;
- }
-
- return 0;
-}
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
-
-int LWS_WARN_UNUSED_RESULT
-lws_http_transaction_completed_client(struct lws *wsi)
-{
- struct lws *wsi_eff = lws_client_wsi_effective(wsi);
-
- lwsl_info("%s: wsi: %p, wsi_eff: %p (%s)\n", __func__, wsi, wsi_eff,
- wsi_eff->protocol->name);
-
- if (user_callback_handle_rxflow(wsi_eff->protocol->callback, wsi_eff,
- LWS_CALLBACK_COMPLETED_CLIENT_HTTP,
- wsi_eff->user_space, NULL, 0)) {
- lwsl_debug("%s: Completed call returned nonzero (role 0x%lx)\n",
- __func__, (unsigned long)lwsi_role(wsi_eff));
- return -1;
- }
-
- /*
- * Are we constitutionally capable of having a queue, ie, we are on
- * the "active client connections" list?
- *
- * If not, that's it for us.
- */
-
- if (lws_dll2_is_detached(&wsi->dll_cli_active_conns))
- return -1;
-
- /* if this was a queued guy, close him and remove from queue */
-
- if (wsi->transaction_from_pipeline_queue) {
- lwsl_debug("closing queued wsi %p\n", wsi_eff);
- /* so the close doesn't trigger a CCE */
- wsi_eff->already_did_cce = 1;
- __lws_close_free_wsi(wsi_eff,
- LWS_CLOSE_STATUS_CLIENT_TRANSACTION_DONE,
- "queued client done");
- }
-
- _lws_header_table_reset(wsi->http.ah);
-
- /* after the first one, they can only be coming from the queue */
- wsi->transaction_from_pipeline_queue = 1;
-
- wsi->http.rx_content_length = 0;
- wsi->hdr_parsing_completed = 0;
-
- /* is there a new tail after removing that one? */
- wsi_eff = lws_client_wsi_effective(wsi);
-
- /*
- * Do we have something pipelined waiting?
- * it's OK if he hasn't managed to send his headers yet... he's next
- * in line to do that...
- */
- if (wsi_eff == wsi) {
- /*
- * Nothing pipelined... we should hang around a bit
- * in case something turns up...
- */
- lwsl_info("%s: nothing pipelined waiting\n", __func__);
- lwsi_set_state(wsi, LRS_IDLING);
-
- lws_set_timeout(wsi, PENDING_TIMEOUT_CLIENT_CONN_IDLE, 5);
-
- return 0;
- }
-
- /*
- * H1: we can serialize the queued guys into the same ah
- * H2: everybody needs their own ah until their own STREAM_END
- */
-
- /* otherwise set ourselves up ready to go again */
- lwsi_set_state(wsi, LRS_WAITING_SERVER_REPLY);
-
- wsi->http.ah->parser_state = WSI_TOKEN_NAME_PART;
- wsi->http.ah->lextable_pos = 0;
-#if defined(LWS_WITH_CUSTOM_HEADERS)
- wsi->http.ah->unk_pos = 0;
-#endif
-
- lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
- wsi->context->timeout_secs);
-
- /* If we're (re)starting on headers, need other implied init */
- wsi->http.ah->ues = URIES_IDLE;
-
- lwsl_info("%s: %p: new queued transaction as %p\n", __func__, wsi,
- wsi_eff);
- lws_callback_on_writable(wsi);
-
- return 0;
-}
-
-LWS_VISIBLE LWS_EXTERN unsigned int
-lws_http_client_http_response(struct lws *_wsi)
-{
- struct lws *wsi;
- unsigned int resp;
-
- if (_wsi->http.ah && _wsi->http.ah->http_response)
- return _wsi->http.ah->http_response;
-
- lws_vhost_lock(_wsi->vhost);
- wsi = _lws_client_wsi_master(_wsi);
- resp = wsi->http.ah->http_response;
- lws_vhost_unlock(_wsi->vhost);
-
- return resp;
-}
-#endif
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
-int
-lws_client_interpret_server_handshake(struct lws *wsi)
-{
- int n, port = 0, ssl = 0;
- int close_reason = LWS_CLOSE_STATUS_PROTOCOL_ERR;
- const char *prot, *ads = NULL, *path, *cce = NULL;
- struct allocated_headers *ah;
- struct lws *w = lws_client_wsi_effective(wsi);
- char *p, *q;
- char new_path[300];
-
- lws_client_stash_destroy(wsi);
-
- ah = wsi->http.ah;
- if (!wsi->do_ws) {
- /* we are being an http client...
- */
-#if defined(LWS_ROLE_H2)
- if (wsi->client_h2_alpn || wsi->client_h2_substream) {
- lwsl_debug("%s: %p: transitioning to h2 client\n",
- __func__, wsi);
- lws_role_transition(wsi, LWSIFR_CLIENT,
- LRS_ESTABLISHED, &role_ops_h2);
- } else
-#endif
- {
-#if defined(LWS_ROLE_H1)
- {
- lwsl_debug("%s: %p: transitioning to h1 client\n",
- __func__, wsi);
- lws_role_transition(wsi, LWSIFR_CLIENT,
- LRS_ESTABLISHED, &role_ops_h1);
- }
-#else
- return -1;
-#endif
- }
-
- wsi->http.ah = ah;
- ah->http_response = 0;
- }
-
- /*
- * well, what the server sent looked reasonable for syntax.
- * Now let's confirm it sent all the necessary headers
- *
- * http (non-ws) client will expect something like this
- *
- * HTTP/1.0.200
- * server:.libwebsockets
- * content-type:.text/html
- * content-length:.17703
- * set-cookie:.test=LWS_1456736240_336776_COOKIE;Max-Age=360000
- */
-
- wsi->http.conn_type = HTTP_CONNECTION_KEEP_ALIVE;
- if (!wsi->client_h2_substream) {
- p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP);
- if (wsi->do_ws && !p) {
- lwsl_info("no URI\n");
- cce = "HS: URI missing";
- goto bail3;
- }
- if (!p) {
- p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP1_0);
- wsi->http.conn_type = HTTP_CONNECTION_CLOSE;
- }
- if (!p) {
- cce = "HS: URI missing";
- lwsl_info("no URI\n");
- goto bail3;
- }
- } else {
- p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_STATUS);
- if (!p) {
- cce = "HS: :status missing";
- lwsl_info("no status\n");
- goto bail3;
- }
- }
- n = atoi(p);
- if (ah)
- ah->http_response = n;
-
- if (
-#if defined(LWS_WITH_HTTP_PROXY)
- !wsi->http.proxy_clientside &&
-#endif
- (n == 301 || n == 302 || n == 303 || n == 307 || n == 308)) {
- p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_LOCATION);
- if (!p) {
- cce = "HS: Redirect code but no Location";
- goto bail3;
- }
-
- /* Relative reference absolute path */
- if (p[0] == '/') {
-#if defined(LWS_WITH_TLS)
- ssl = wsi->tls.use_ssl & LCCSCF_USE_SSL;
-#endif
- ads = lws_hdr_simple_ptr(wsi,
- _WSI_TOKEN_CLIENT_PEER_ADDRESS);
- port = wsi->c_port;
- /* +1 as lws_client_reset expects leading / omitted */
- path = p + 1;
- }
- /* Absolute (Full) URI */
- else if (strchr(p, ':')) {
- if (lws_parse_uri(p, &prot, &ads, &port, &path)) {
- cce = "HS: URI did not parse";
- goto bail3;
- }
-
- if (!strcmp(prot, "wss") || !strcmp(prot, "https"))
- ssl = 1;
- }
- /* Relative reference relative path */
- else {
- /* This doesn't try to calculate an absolute path,
- * that will be left to the server */
-#if defined(LWS_WITH_TLS)
- ssl = wsi->tls.use_ssl & LCCSCF_USE_SSL;
-#endif
- ads = lws_hdr_simple_ptr(wsi,
- _WSI_TOKEN_CLIENT_PEER_ADDRESS);
- port = wsi->c_port;
- /* +1 as lws_client_reset expects leading / omitted */
- path = new_path + 1;
- if (lws_hdr_simple_ptr(wsi,_WSI_TOKEN_CLIENT_URI))
- lws_strncpy(new_path, lws_hdr_simple_ptr(wsi,
- _WSI_TOKEN_CLIENT_URI), sizeof(new_path));
- else {
- new_path[0] = '/';
- new_path[1] = '\0';
- }
- q = strrchr(new_path, '/');
- if (q)
- lws_strncpy(q + 1, p, sizeof(new_path) -
- (q - new_path) - 1);
- else
- path = p;
- }
-
-#if defined(LWS_WITH_TLS)
- if ((wsi->tls.use_ssl & LCCSCF_USE_SSL) && !ssl) {
- cce = "HS: Redirect attempted SSL downgrade";
- goto bail3;
- }
-#endif
-
- if (!ads) /* make coverity happy */ {
- cce = "no ads";
- goto bail3;
- }
-
- if (!lws_client_reset(&wsi, ssl, ads, port, path, ads)) {
- /* there are two ways to fail out with NULL return...
- * simple, early problem where the wsi is intact, or
- * we went through with the reconnect attempt and the
- * wsi is already closed. In the latter case, the wsi
- * has beet set to NULL additionally.
- */
- lwsl_err("Redirect failed\n");
- cce = "HS: Redirect failed";
- if (wsi)
- goto bail3;
-
- return 1;
- }
- return 0;
- }
-
- if (!wsi->do_ws) {
-
- /* if h1 KA is allowed, enable the queued pipeline guys */
-
- if (!wsi->client_h2_alpn && !wsi->client_h2_substream &&
- w == wsi) { /* ie, coming to this for the first time */
- if (wsi->http.conn_type == HTTP_CONNECTION_KEEP_ALIVE)
- wsi->keepalive_active = 1;
- else {
- /*
- * Ugh... now the main http connection has seen
- * both sides, we learn the server doesn't
- * support keepalive.
- *
- * That means any guys queued on us are going
- * to have to be restarted from connect2 with
- * their own connections.
- */
-
- /*
- * stick around telling any new guys they can't
- * pipeline to this server
- */
- wsi->keepalive_rejected = 1;
-
- lws_vhost_lock(wsi->vhost);
- lws_start_foreach_dll_safe(struct lws_dll2 *,
- d, d1,
- wsi->dll2_cli_txn_queue_owner.head) {
- struct lws *ww = lws_container_of(d,
- struct lws,
- dll2_cli_txn_queue);
-
- /* remove him from our queue */
- lws_dll2_remove(&ww->dll2_cli_txn_queue);
- /* give up on pipelining */
- ww->client_pipeline = 0;
-
- /* go back to "trying to connect" state */
- lws_role_transition(ww, LWSIFR_CLIENT,
- LRS_UNCONNECTED,
-#if defined(LWS_ROLE_H1)
- &role_ops_h1);
-#else
-#if defined (LWS_ROLE_H2)
- &role_ops_h2);
-#else
- &role_ops_raw);
-#endif
-#endif
- ww->user_space = NULL;
- } lws_end_foreach_dll_safe(d, d1);
- lws_vhost_unlock(wsi->vhost);
- }
- }
-
-#ifdef LWS_WITH_HTTP_PROXY
- wsi->http.perform_rewrite = 0;
- if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE)) {
- if (!strncmp(lws_hdr_simple_ptr(wsi,
- WSI_TOKEN_HTTP_CONTENT_TYPE),
- "text/html", 9))
- wsi->http.perform_rewrite = 0;
- }
-#endif
-
- /* allocate the per-connection user memory (if any) */
- if (lws_ensure_user_space(wsi)) {
- lwsl_err("Problem allocating wsi user mem\n");
- cce = "HS: OOM";
- goto bail2;
- }
-
- /* he may choose to send us stuff in chunked transfer-coding */
- wsi->chunked = 0;
- wsi->chunk_remaining = 0; /* ie, next thing is chunk size */
- if (lws_hdr_total_length(wsi,
- WSI_TOKEN_HTTP_TRANSFER_ENCODING)) {
- wsi->chunked = !strcmp(lws_hdr_simple_ptr(wsi,
- WSI_TOKEN_HTTP_TRANSFER_ENCODING),
- "chunked");
- /* first thing is hex, after payload there is crlf */
- wsi->chunk_parser = ELCP_HEX;
- }
-
- if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
- wsi->http.rx_content_length =
- atoll(lws_hdr_simple_ptr(wsi,
- WSI_TOKEN_HTTP_CONTENT_LENGTH));
- lwsl_info("%s: incoming content length %llu\n",
- __func__, (unsigned long long)
- wsi->http.rx_content_length);
- wsi->http.rx_content_remain =
- wsi->http.rx_content_length;
- } else /* can't do 1.1 without a content length or chunked */
- if (!wsi->chunked)
- wsi->http.conn_type = HTTP_CONNECTION_CLOSE;
-
- /*
- * we seem to be good to go, give client last chance to check
- * headers and OK it
- */
- if (w->protocol->callback(w,
- LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH,
- w->user_space, NULL, 0)) {
-
- cce = "HS: disallowed by client filter";
- goto bail2;
- }
-
- /* clear his proxy connection timeout */
- lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
-
- wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
-
- /* call him back to inform him he is up */
- if (w->protocol->callback(w,
- LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP,
- w->user_space, NULL, 0)) {
- cce = "HS: disallowed at ESTABLISHED";
- goto bail3;
- }
-
- /*
- * for pipelining, master needs to keep his ah... guys who
- * queued on him can drop it now though.
- */
-
- if (w != wsi)
- /* free up parsing allocations for queued guy */
- lws_header_table_detach(w, 0);
-
- lwsl_info("%s: client connection up\n", __func__);
-
- /*
- * Did we get a response from the server with an explicit
- * content-length of zero? If so, this transaction is already
- * completed at the end of the header processing...
- */
- if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH) &&
- !wsi->http.rx_content_length)
- return !!lws_http_transaction_completed_client(wsi);
-
- return 0;
- }
-
-#if defined(LWS_ROLE_WS)
- switch (lws_client_ws_upgrade(wsi, &cce)) {
- case 2:
- goto bail2;
- case 3:
- goto bail3;
- }
-
- return 0;
-#endif
-
-bail3:
- close_reason = LWS_CLOSE_STATUS_NOSTATUS;
-
-bail2:
- if (wsi->protocol) {
- n = 0;
- if (cce)
- n = (int)strlen(cce);
-
- lws_inform_client_conn_fail(wsi, (void *)cce, (unsigned int)n);
- }
-
- lwsl_info("closing connection (prot %s) "
- "due to bail2 connection error: %s\n", wsi->protocol ?
- wsi->protocol->name : "unknown", cce);
-
- /* closing will free up his parsing allocations */
- lws_close_free_wsi(wsi, close_reason, "c hs interp");
-
- return 1;
-}
-#endif
-
-char *
-lws_generate_client_handshake(struct lws *wsi, char *pkt)
-{
- char *p = pkt;
- const char *meth;
- const char *pp = lws_hdr_simple_ptr(wsi,
- _WSI_TOKEN_CLIENT_SENT_PROTOCOLS);
-
- meth = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_METHOD);
- if (!meth) {
- meth = "GET";
- wsi->do_ws = 1;
- } else {
- wsi->do_ws = 0;
- }
-
- if (!strcmp(meth, "RAW")) {
- lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
- lwsl_notice("client transition to raw\n");
-
- if (pp) {
- const struct lws_protocols *pr;
-
- pr = lws_vhost_name_to_protocol(wsi->vhost, pp);
-
- if (!pr) {
- lwsl_err("protocol %s not enabled on vhost\n",
- pp);
- return NULL;
- }
-
- lws_bind_protocol(wsi, pr, __func__);
- }
-
- if ((wsi->protocol->callback)(wsi, LWS_CALLBACK_RAW_ADOPT,
- wsi->user_space, NULL, 0))
- return NULL;
-
- lws_role_transition(wsi, LWSIFR_CLIENT, LRS_ESTABLISHED,
- &role_ops_raw_skt);
- lws_header_table_detach(wsi, 1);
-
- return NULL;
- }
-
- /*
- * 04 example client handshake
- *
- * GET /chat HTTP/1.1
- * Host: server.example.com
- * Upgrade: websocket
- * Connection: Upgrade
- * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
- * Sec-WebSocket-Origin: http://example.com
- * Sec-WebSocket-Protocol: chat, superchat
- * Sec-WebSocket-Version: 4
- */
-
- p += lws_snprintf(p, 2048, "%s %s HTTP/1.1\x0d\x0a", meth,
- lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI));
-
- p += lws_snprintf(p, 64, "Pragma: no-cache\x0d\x0a"
- "Cache-Control: no-cache\x0d\x0a");
-
- p += lws_snprintf(p, 128, "Host: %s\x0d\x0a",
- lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST));
-
- if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN)) {
- if (lws_check_opt(wsi->context->options,
- LWS_SERVER_OPTION_JUST_USE_RAW_ORIGIN))
- p += lws_snprintf(p, 128, "Origin: %s\x0d\x0a",
- lws_hdr_simple_ptr(wsi,
- _WSI_TOKEN_CLIENT_ORIGIN));
- else
- p += lws_snprintf(p, 128, "Origin: http://%s\x0d\x0a",
- lws_hdr_simple_ptr(wsi,
- _WSI_TOKEN_CLIENT_ORIGIN));
- }
-
-#if defined(LWS_WITH_HTTP_PROXY)
- if (wsi->parent &&
- lws_hdr_total_length(wsi->parent, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
- p += lws_snprintf(p, 128, "Content-Length: %s\x0d\x0a",
- lws_hdr_simple_ptr(wsi->parent, WSI_TOKEN_HTTP_CONTENT_LENGTH));
- if (atoi(lws_hdr_simple_ptr(wsi->parent, WSI_TOKEN_HTTP_CONTENT_LENGTH)))
- wsi->client_http_body_pending = 1;
- }
- if (wsi->parent &&
- lws_hdr_total_length(wsi->parent, WSI_TOKEN_HTTP_AUTHORIZATION)) {
- p += lws_snprintf(p, 128, "Authorization: %s\x0d\x0a",
- lws_hdr_simple_ptr(wsi->parent, WSI_TOKEN_HTTP_AUTHORIZATION));
- }
- if (wsi->parent &&
- lws_hdr_total_length(wsi->parent, WSI_TOKEN_HTTP_CONTENT_TYPE)) {
- p += lws_snprintf(p, 128, "Content-Type: %s\x0d\x0a",
- lws_hdr_simple_ptr(wsi->parent, WSI_TOKEN_HTTP_CONTENT_TYPE));
- }
-#endif
-
-#if defined(LWS_ROLE_WS)
- if (wsi->do_ws) {
- const char *conn1 = "";
- // if (!wsi->client_pipeline)
- // conn1 = "close, ";
- p = lws_generate_client_ws_handshake(wsi, p, conn1);
- } else
-#endif
- {
- if (!wsi->client_pipeline)
- p += lws_snprintf(p, 64, "connection: close\x0d\x0a");
- }
-
- /* give userland a chance to append, eg, cookies */
-
- if (wsi->protocol->callback(wsi,
- LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
- wsi->user_space, &p,
- (pkt + wsi->context->pt_serv_buf_size) - p - 12))
- return NULL;
-
- p += lws_snprintf(p, 4, "\x0d\x0a");
-
- // puts(pkt);
-
- return p;
-}
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
-
-LWS_VISIBLE int
-lws_http_client_read(struct lws *wsi, char **buf, int *len)
-{
- int rlen, n;
-
- rlen = lws_ssl_capable_read(wsi, (unsigned char *)*buf, *len);
- *len = 0;
-
- // lwsl_notice("%s: rlen %d\n", __func__, rlen);
-
- /* allow the source to signal he has data again next time */
- if (lws_change_pollfd(wsi, 0, LWS_POLLIN))
- return -1;
-
- if (rlen == LWS_SSL_CAPABLE_ERROR) {
- lwsl_debug("%s: SSL capable error\n", __func__);
- return -1;
- }
-
- if (rlen <= 0)
- return 0;
-
- *len = rlen;
- wsi->client_rx_avail = 0;
-
- /*
- * server may insist on transfer-encoding: chunked,
- * so http client must deal with it
- */
-spin_chunks:
- while (wsi->chunked && (wsi->chunk_parser != ELCP_CONTENT) && *len) {
- switch (wsi->chunk_parser) {
- case ELCP_HEX:
- if ((*buf)[0] == '\x0d') {
- wsi->chunk_parser = ELCP_CR;
- break;
- }
- n = char_to_hex((*buf)[0]);
- if (n < 0) {
- lwsl_info("%s: chunking failure\n", __func__);
- return -1;
- }
- wsi->chunk_remaining <<= 4;
- wsi->chunk_remaining |= n;
- break;
- case ELCP_CR:
- if ((*buf)[0] != '\x0a') {
- lwsl_info("%s: chunking failure\n", __func__);
- return -1;
- }
- wsi->chunk_parser = ELCP_CONTENT;
- lwsl_info("chunk %d\n", wsi->chunk_remaining);
- if (wsi->chunk_remaining)
- break;
- lwsl_info("final chunk\n");
- goto completed;
-
- case ELCP_CONTENT:
- break;
-
- case ELCP_POST_CR:
- if ((*buf)[0] != '\x0d') {
- lwsl_info("%s: chunking failure\n", __func__);
-
- return -1;
- }
-
- wsi->chunk_parser = ELCP_POST_LF;
- break;
-
- case ELCP_POST_LF:
- if ((*buf)[0] != '\x0a') {
- lwsl_info("%s: chunking failure\n", __func__);
-
- return -1;
- }
-
- wsi->chunk_parser = ELCP_HEX;
- wsi->chunk_remaining = 0;
- break;
- }
- (*buf)++;
- (*len)--;
- }
-
- if (wsi->chunked && !wsi->chunk_remaining)
- return 0;
-
- if (wsi->http.rx_content_remain &&
- wsi->http.rx_content_remain < (unsigned int)*len)
- n = (int)wsi->http.rx_content_remain;
- else
- n = *len;
-
- if (wsi->chunked && wsi->chunk_remaining &&
- wsi->chunk_remaining < n)
- n = wsi->chunk_remaining;
-
-#if defined(LWS_WITH_HTTP_PROXY) && defined(LWS_WITH_HUBBUB)
- /* hubbub */
- if (wsi->http.perform_rewrite)
- lws_rewrite_parse(wsi->http.rw, (unsigned char *)*buf, n);
- else
-#endif
- {
- struct lws *wsi_eff = lws_client_wsi_effective(wsi);
-
- if (
-#if defined(LWS_WITH_HTTP_PROXY)
- !wsi_eff->protocol_bind_balance ==
- !!wsi_eff->http.proxy_clientside &&
-#else
- !!wsi_eff->protocol_bind_balance &&
-#endif
- user_callback_handle_rxflow(wsi_eff->protocol->callback,
- wsi_eff, LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ,
- wsi_eff->user_space, *buf, n)) {
- lwsl_info("%s: RECEIVE_CLIENT_HTTP_READ returned -1\n",
- __func__);
-
- return -1;
- }
- }
-
- if (wsi->chunked && wsi->chunk_remaining) {
- (*buf) += n;
- wsi->chunk_remaining -= n;
- *len -= n;
- }
-
- if (wsi->chunked && !wsi->chunk_remaining)
- wsi->chunk_parser = ELCP_POST_CR;
-
- if (wsi->chunked && *len)
- goto spin_chunks;
-
- if (wsi->chunked)
- return 0;
-
- /* if we know the content length, decrement the content remaining */
- if (wsi->http.rx_content_length > 0)
- wsi->http.rx_content_remain -= n;
-
- // lwsl_notice("rx_content_remain %lld, rx_content_length %lld\n",
- // wsi->http.rx_content_remain, wsi->http.rx_content_length);
-
- if (wsi->http.rx_content_remain || !wsi->http.rx_content_length)
- return 0;
-
-completed:
-
- if (lws_http_transaction_completed_client(wsi)) {
- lwsl_notice("%s: transaction completed says -1\n", __func__);
- return -1;
- }
-
- return 0;
-}
-
-#endif
The compression transforms expose an "ops" type struct and a compressor name
as used by `content-encoding`... the ops struct definition can be found in
-./private.h.
+./private-lib-roles-http-compression.h.
Because the compression transform depends on being able to send on its output
before it can process new input, the transform adds a new kind of buflist
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
static int
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
static int
lcs_init_compression_deflate(lws_comp_ctx_t *ctx, int decomp)
--- /dev/null
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010 - 2018 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
+ *
+ * This is included from private-lib-core.h if LWS_WITH_HTTP_STREAM_COMPRESSION
+ */
+
+#if defined(LWS_WITH_MINIZ)
+#include <miniz.h>
+#else
+#include <zlib.h>
+#endif
+#if defined(LWS_WITH_HTTP_BROTLI)
+#include <brotli/encode.h>
+#include <brotli/decode.h>
+#endif
+
+/*
+ * struct holding union of all the available compression methods' context data,
+ * and state if it's compressing or decompressing
+ */
+
+typedef struct lws_compression_ctx {
+ union {
+
+#if defined(LWS_WITH_HTTP_BROTLI)
+ BrotliEncoderState *br_en;
+ BrotliDecoderState *br_de;
+#endif
+ z_stream *deflate;
+ void *generic_ctx_ptr;
+ } u;
+
+ struct lws_buflist *buflist_comp;
+
+ unsigned int is_decompression:1;
+ unsigned int final_on_input_side:1;
+ unsigned int may_have_more:1;
+ unsigned int chunking:1;
+} lws_comp_ctx_t;
+
+/* generic structure defining the interface to a compression method */
+
+struct lws_compression_support {
+ /** compression name as used by, eg, content-ecoding */
+ const char *encoding_name;
+ /** create a compression context for the compression method, or NULL */
+ int (*init_compression)(lws_comp_ctx_t *ctx, int decomp);
+ /** pass data into the context to be processed */
+ int (*process)(lws_comp_ctx_t *ctx, const void *in, size_t *ilen_iused,
+ void *out, size_t *olen_oused);
+ /** destroy the de/compression context */
+ void (*destroy)(lws_comp_ctx_t *ctx);
+};
+
+extern struct lws_compression_support lcs_deflate;
+extern struct lws_compression_support lcs_brotli;
+
+int
+lws_http_compression_validate(struct lws *wsi);
+
+int
+lws_http_compression_transform(struct lws *wsi, unsigned char *buf,
+ size_t len, enum lws_write_protocol *wp,
+ unsigned char **outbuf, size_t *olen_oused);
+
+void
+lws_http_compression_destroy(struct lws *wsi);
+++ /dev/null
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 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
- *
- * This is included from core/private.h if LWS_WITH_HTTP_STREAM_COMPRESSION
- */
-
-#if defined(LWS_WITH_MINIZ)
-#include <miniz.h>
-#else
-#include <zlib.h>
-#endif
-#if defined(LWS_WITH_HTTP_BROTLI)
-#include <brotli/encode.h>
-#include <brotli/decode.h>
-#endif
-
-/*
- * struct holding union of all the available compression methods' context data,
- * and state if it's compressing or decompressing
- */
-
-typedef struct lws_compression_ctx {
- union {
-
-#if defined(LWS_WITH_HTTP_BROTLI)
- BrotliEncoderState *br_en;
- BrotliDecoderState *br_de;
-#endif
- z_stream *deflate;
- void *generic_ctx_ptr;
- } u;
-
- struct lws_buflist *buflist_comp;
-
- unsigned int is_decompression:1;
- unsigned int final_on_input_side:1;
- unsigned int may_have_more:1;
- unsigned int chunking:1;
-} lws_comp_ctx_t;
-
-/* generic structure defining the interface to a compression method */
-
-struct lws_compression_support {
- /** compression name as used by, eg, content-ecoding */
- const char *encoding_name;
- /** create a compression context for the compression method, or NULL */
- int (*init_compression)(lws_comp_ctx_t *ctx, int decomp);
- /** pass data into the context to be processed */
- int (*process)(lws_comp_ctx_t *ctx, const void *in, size_t *ilen_iused,
- void *out, size_t *olen_oused);
- /** destroy the de/compression context */
- void (*destroy)(lws_comp_ctx_t *ctx);
-};
-
-extern struct lws_compression_support lcs_deflate;
-extern struct lws_compression_support lcs_brotli;
-
-int
-lws_http_compression_validate(struct lws *wsi);
-
-int
-lws_http_compression_transform(struct lws *wsi, unsigned char *buf,
- size_t len, enum lws_write_protocol *wp,
- unsigned char **outbuf, size_t *olen_oused);
-
-void
-lws_http_compression_destroy(struct lws *wsi);
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
/* compression methods listed in order of preference */
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
#include "lextable-strings.h"
--- /dev/null
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010 - 2018 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
+ *
+ * This is included from private-lib-core.h if either H1 or H2 roles are
+ * enabled
+ */
+
+#if defined(LWS_WITH_HUBBUB)
+ #include <hubbub/hubbub.h>
+ #include <hubbub/parser.h>
+ #endif
+
+#if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
+#include "private-lib-roles-http-compression.h"
+#endif
+
+#define lwsi_role_http(wsi) (lwsi_role_h1(wsi) || lwsi_role_h2(wsi))
+
+enum http_version {
+ HTTP_VERSION_1_0,
+ HTTP_VERSION_1_1,
+ HTTP_VERSION_2
+};
+
+enum http_conn_type {
+ HTTP_CONNECTION_CLOSE,
+ HTTP_CONNECTION_KEEP_ALIVE
+};
+
+/*
+ * This is totally opaque to code using the library. It's exported as a
+ * forward-reference pointer-only declaration; the user can use the pointer with
+ * other APIs to get information out of it.
+ */
+
+#if defined(LWS_WITH_ESP32)
+typedef uint16_t ah_data_idx_t;
+#else
+typedef uint32_t ah_data_idx_t;
+#endif
+
+struct lws_fragments {
+ ah_data_idx_t offset;
+ uint16_t len;
+ uint8_t nfrag; /* which ah->frag[] continues this content, or 0 */
+ uint8_t flags; /* only http2 cares */
+};
+
+#if defined(LWS_WITH_RANGES)
+enum range_states {
+ LWSRS_NO_ACTIVE_RANGE,
+ LWSRS_BYTES_EQ,
+ LWSRS_FIRST,
+ LWSRS_STARTING,
+ LWSRS_ENDING,
+ LWSRS_COMPLETED,
+ LWSRS_SYNTAX,
+};
+
+struct lws_range_parsing {
+ unsigned long long start, end, extent, agg, budget;
+ const char buf[128];
+ int pos;
+ enum range_states state;
+ char start_valid, end_valid, ctr, count_ranges, did_try, inside, send_ctr;
+};
+
+int
+lws_ranges_init(struct lws *wsi, struct lws_range_parsing *rp,
+ unsigned long long extent);
+int
+lws_ranges_next(struct lws_range_parsing *rp);
+void
+lws_ranges_reset(struct lws_range_parsing *rp);
+#endif
+
+/*
+ * these are assigned from a pool held in the context.
+ * Both client and server mode uses them for http header analysis
+ */
+
+struct allocated_headers {
+ struct allocated_headers *next; /* linked list */
+ struct lws *wsi; /* owner */
+ char *data; /* prepared by context init to point to dedicated storage */
+ ah_data_idx_t data_length;
+ /*
+ * the randomly ordered fragments, indexed by frag_index and
+ * lws_fragments->nfrag for continuation.
+ */
+ struct lws_fragments frags[WSI_TOKEN_COUNT];
+ time_t assigned;
+ /*
+ * for each recognized token, frag_index says which frag[] his data
+ * starts in (0 means the token did not appear)
+ * the actual header data gets dumped as it comes in, into data[]
+ */
+ uint8_t frag_index[WSI_TOKEN_COUNT];
+
+#ifndef LWS_NO_CLIENT
+ char initial_handshake_hash_base64[30];
+#endif
+ int hdr_token_idx;
+
+ ah_data_idx_t pos;
+ ah_data_idx_t http_response;
+ ah_data_idx_t current_token_limit;
+
+#if defined(LWS_WITH_CUSTOM_HEADERS)
+ ah_data_idx_t unk_pos; /* to undo speculative unknown header */
+ ah_data_idx_t unk_value_pos;
+
+ ah_data_idx_t unk_ll_head;
+ ah_data_idx_t unk_ll_tail;
+#endif
+
+ int16_t lextable_pos;
+
+ uint8_t in_use;
+ uint8_t nfrag;
+ char /*enum uri_path_states */ ups;
+ char /*enum uri_esc_states */ ues;
+
+ char esc_stash;
+ char post_literal_equal;
+ uint8_t /* enum lws_token_indexes */ parser_state;
+};
+
+
+
+#if defined(LWS_WITH_HUBBUB)
+struct lws_rewrite {
+ hubbub_parser *parser;
+ hubbub_parser_optparams params;
+ const char *from, *to;
+ int from_len, to_len;
+ unsigned char *p, *end;
+ struct lws *wsi;
+};
+static LWS_INLINE int hstrcmp(hubbub_string *s, const char *p, int len)
+{
+ if ((int)s->len != len)
+ return 1;
+
+ return strncmp((const char *)s->ptr, p, len);
+}
+typedef hubbub_error (*hubbub_callback_t)(const hubbub_token *token, void *pw);
+LWS_EXTERN struct lws_rewrite *
+lws_rewrite_create(struct lws *wsi, hubbub_callback_t cb, const char *from, const char *to);
+LWS_EXTERN void
+lws_rewrite_destroy(struct lws_rewrite *r);
+LWS_EXTERN int
+lws_rewrite_parse(struct lws_rewrite *r, const unsigned char *in, int in_len);
+#endif
+
+struct lws_pt_role_http {
+ struct allocated_headers *ah_list;
+ struct lws *ah_wait_list;
+#ifdef LWS_WITH_CGI
+ struct lws_cgi *cgi_list;
+#endif
+ int ah_wait_list_length;
+ uint32_t ah_pool_length;
+
+ int ah_count_in_use;
+};
+
+struct lws_peer_role_http {
+ uint32_t count_ah;
+ uint32_t total_ah;
+};
+
+struct lws_vhost_role_http {
+ char http_proxy_address[128];
+ const struct lws_http_mount *mount_list;
+ const char *error_document_404;
+ unsigned int http_proxy_port;
+};
+
+#ifdef LWS_WITH_ACCESS_LOG
+struct lws_access_log {
+ char *header_log;
+ char *user_agent;
+ char *referrer;
+ unsigned long sent;
+ int response;
+};
+#endif
+
+#define LWS_HTTP_CHUNK_HDR_MAX_SIZE (6 + 2) /* 6 hex digits and then CRLF */
+#define LWS_HTTP_CHUNK_TRL_MAX_SIZE (2 + 5) /* CRLF, then maybe 0 CRLF CRLF */
+
+struct _lws_http_mode_related {
+ struct lws *new_wsi_list;
+
+ unsigned char *pending_return_headers;
+ size_t pending_return_headers_len;
+ size_t prh_content_length;
+
+#if defined(LWS_WITH_HTTP_PROXY)
+ struct lws_rewrite *rw;
+ struct lws_buflist *buflist_post_body;
+#endif
+ struct allocated_headers *ah;
+ struct lws *ah_wait_list;
+
+ lws_filepos_t filepos;
+ lws_filepos_t filelen;
+ lws_fop_fd_t fop_fd;
+
+#if defined(LWS_WITH_RANGES)
+ struct lws_range_parsing range;
+ char multipart_content_type[64];
+#endif
+
+#ifdef LWS_WITH_ACCESS_LOG
+ struct lws_access_log access_log;
+#endif
+#ifdef LWS_WITH_CGI
+ struct lws_cgi *cgi; /* wsi being cgi master have one of these */
+#endif
+#if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
+ struct lws_compression_support *lcs;
+ lws_comp_ctx_t comp_ctx;
+ unsigned char comp_accept_mask;
+#endif
+
+ enum http_version request_version;
+ enum http_conn_type conn_type;
+ lws_filepos_t tx_content_length;
+ lws_filepos_t tx_content_remain;
+ lws_filepos_t rx_content_length;
+ lws_filepos_t rx_content_remain;
+
+#if defined(LWS_WITH_HTTP_PROXY)
+ unsigned int perform_rewrite:1;
+ unsigned int proxy_clientside:1;
+ unsigned int proxy_parent_chunked:1;
+#endif
+ unsigned int deferred_transaction_completed:1;
+ unsigned int content_length_explicitly_zero:1;
+ unsigned int did_stream_close:1;
+};
+
+
+#ifndef LWS_NO_CLIENT
+enum lws_chunk_parser {
+ ELCP_HEX,
+ ELCP_CR,
+ ELCP_CONTENT,
+ ELCP_POST_CR,
+ ELCP_POST_LF,
+};
+#endif
+
+enum lws_parse_urldecode_results {
+ LPUR_CONTINUE,
+ LPUR_SWALLOW,
+ LPUR_FORBID,
+ LPUR_EXCESSIVE,
+};
+
+enum lws_check_basic_auth_results {
+ LCBA_CONTINUE,
+ LCBA_FAILED_AUTH,
+ LCBA_END_TRANSACTION,
+};
+
+enum lws_check_basic_auth_results
+lws_check_basic_auth(struct lws *wsi, const char *basic_auth_login_file);
+
+int
+lws_unauthorised_basic_auth(struct lws *wsi);
+
+int
+lws_read_h1(struct lws *wsi, unsigned char *buf, lws_filepos_t len);
+
+void
+_lws_header_table_reset(struct allocated_headers *ah);
+
+LWS_EXTERN int
+_lws_destroy_ah(struct lws_context_per_thread *pt, struct allocated_headers *ah);
+
+int
+lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit,
+ char *uri_ptr, char ws);
+
+typedef struct lws_sorted_usec_list lws_sorted_usec_list_t;
+
+void
+lws_sul_http_ah_lifecheck(lws_sorted_usec_list_t *sul);
+++ /dev/null
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 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
- *
- * This is included from core/private.h if either H1 or H2 roles are
- * enabled
- */
-
-#if defined(LWS_WITH_HUBBUB)
- #include <hubbub/hubbub.h>
- #include <hubbub/parser.h>
- #endif
-
-#if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
-#include "roles/http/compression/private.h"
-#endif
-
-#define lwsi_role_http(wsi) (lwsi_role_h1(wsi) || lwsi_role_h2(wsi))
-
-enum http_version {
- HTTP_VERSION_1_0,
- HTTP_VERSION_1_1,
- HTTP_VERSION_2
-};
-
-enum http_conn_type {
- HTTP_CONNECTION_CLOSE,
- HTTP_CONNECTION_KEEP_ALIVE
-};
-
-/*
- * This is totally opaque to code using the library. It's exported as a
- * forward-reference pointer-only declaration; the user can use the pointer with
- * other APIs to get information out of it.
- */
-
-#if defined(LWS_WITH_ESP32)
-typedef uint16_t ah_data_idx_t;
-#else
-typedef uint32_t ah_data_idx_t;
-#endif
-
-struct lws_fragments {
- ah_data_idx_t offset;
- uint16_t len;
- uint8_t nfrag; /* which ah->frag[] continues this content, or 0 */
- uint8_t flags; /* only http2 cares */
-};
-
-#if defined(LWS_WITH_RANGES)
-enum range_states {
- LWSRS_NO_ACTIVE_RANGE,
- LWSRS_BYTES_EQ,
- LWSRS_FIRST,
- LWSRS_STARTING,
- LWSRS_ENDING,
- LWSRS_COMPLETED,
- LWSRS_SYNTAX,
-};
-
-struct lws_range_parsing {
- unsigned long long start, end, extent, agg, budget;
- const char buf[128];
- int pos;
- enum range_states state;
- char start_valid, end_valid, ctr, count_ranges, did_try, inside, send_ctr;
-};
-
-int
-lws_ranges_init(struct lws *wsi, struct lws_range_parsing *rp,
- unsigned long long extent);
-int
-lws_ranges_next(struct lws_range_parsing *rp);
-void
-lws_ranges_reset(struct lws_range_parsing *rp);
-#endif
-
-/*
- * these are assigned from a pool held in the context.
- * Both client and server mode uses them for http header analysis
- */
-
-struct allocated_headers {
- struct allocated_headers *next; /* linked list */
- struct lws *wsi; /* owner */
- char *data; /* prepared by context init to point to dedicated storage */
- ah_data_idx_t data_length;
- /*
- * the randomly ordered fragments, indexed by frag_index and
- * lws_fragments->nfrag for continuation.
- */
- struct lws_fragments frags[WSI_TOKEN_COUNT];
- time_t assigned;
- /*
- * for each recognized token, frag_index says which frag[] his data
- * starts in (0 means the token did not appear)
- * the actual header data gets dumped as it comes in, into data[]
- */
- uint8_t frag_index[WSI_TOKEN_COUNT];
-
-#ifndef LWS_NO_CLIENT
- char initial_handshake_hash_base64[30];
-#endif
- int hdr_token_idx;
-
- ah_data_idx_t pos;
- ah_data_idx_t http_response;
- ah_data_idx_t current_token_limit;
-
-#if defined(LWS_WITH_CUSTOM_HEADERS)
- ah_data_idx_t unk_pos; /* to undo speculative unknown header */
- ah_data_idx_t unk_value_pos;
-
- ah_data_idx_t unk_ll_head;
- ah_data_idx_t unk_ll_tail;
-#endif
-
- int16_t lextable_pos;
-
- uint8_t in_use;
- uint8_t nfrag;
- char /*enum uri_path_states */ ups;
- char /*enum uri_esc_states */ ues;
-
- char esc_stash;
- char post_literal_equal;
- uint8_t /* enum lws_token_indexes */ parser_state;
-};
-
-
-
-#if defined(LWS_WITH_HUBBUB)
-struct lws_rewrite {
- hubbub_parser *parser;
- hubbub_parser_optparams params;
- const char *from, *to;
- int from_len, to_len;
- unsigned char *p, *end;
- struct lws *wsi;
-};
-static LWS_INLINE int hstrcmp(hubbub_string *s, const char *p, int len)
-{
- if ((int)s->len != len)
- return 1;
-
- return strncmp((const char *)s->ptr, p, len);
-}
-typedef hubbub_error (*hubbub_callback_t)(const hubbub_token *token, void *pw);
-LWS_EXTERN struct lws_rewrite *
-lws_rewrite_create(struct lws *wsi, hubbub_callback_t cb, const char *from, const char *to);
-LWS_EXTERN void
-lws_rewrite_destroy(struct lws_rewrite *r);
-LWS_EXTERN int
-lws_rewrite_parse(struct lws_rewrite *r, const unsigned char *in, int in_len);
-#endif
-
-struct lws_pt_role_http {
- struct allocated_headers *ah_list;
- struct lws *ah_wait_list;
-#ifdef LWS_WITH_CGI
- struct lws_cgi *cgi_list;
-#endif
- int ah_wait_list_length;
- uint32_t ah_pool_length;
-
- int ah_count_in_use;
-};
-
-struct lws_peer_role_http {
- uint32_t count_ah;
- uint32_t total_ah;
-};
-
-struct lws_vhost_role_http {
- char http_proxy_address[128];
- const struct lws_http_mount *mount_list;
- const char *error_document_404;
- unsigned int http_proxy_port;
-};
-
-#ifdef LWS_WITH_ACCESS_LOG
-struct lws_access_log {
- char *header_log;
- char *user_agent;
- char *referrer;
- unsigned long sent;
- int response;
-};
-#endif
-
-#define LWS_HTTP_CHUNK_HDR_MAX_SIZE (6 + 2) /* 6 hex digits and then CRLF */
-#define LWS_HTTP_CHUNK_TRL_MAX_SIZE (2 + 5) /* CRLF, then maybe 0 CRLF CRLF */
-
-struct _lws_http_mode_related {
- struct lws *new_wsi_list;
-
- unsigned char *pending_return_headers;
- size_t pending_return_headers_len;
- size_t prh_content_length;
-
-#if defined(LWS_WITH_HTTP_PROXY)
- struct lws_rewrite *rw;
- struct lws_buflist *buflist_post_body;
-#endif
- struct allocated_headers *ah;
- struct lws *ah_wait_list;
-
- lws_filepos_t filepos;
- lws_filepos_t filelen;
- lws_fop_fd_t fop_fd;
-
-#if defined(LWS_WITH_RANGES)
- struct lws_range_parsing range;
- char multipart_content_type[64];
-#endif
-
-#ifdef LWS_WITH_ACCESS_LOG
- struct lws_access_log access_log;
-#endif
-#ifdef LWS_WITH_CGI
- struct lws_cgi *cgi; /* wsi being cgi master have one of these */
-#endif
-#if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
- struct lws_compression_support *lcs;
- lws_comp_ctx_t comp_ctx;
- unsigned char comp_accept_mask;
-#endif
-
- enum http_version request_version;
- enum http_conn_type conn_type;
- lws_filepos_t tx_content_length;
- lws_filepos_t tx_content_remain;
- lws_filepos_t rx_content_length;
- lws_filepos_t rx_content_remain;
-
-#if defined(LWS_WITH_HTTP_PROXY)
- unsigned int perform_rewrite:1;
- unsigned int proxy_clientside:1;
- unsigned int proxy_parent_chunked:1;
-#endif
- unsigned int deferred_transaction_completed:1;
- unsigned int content_length_explicitly_zero:1;
- unsigned int did_stream_close:1;
-};
-
-
-#ifndef LWS_NO_CLIENT
-enum lws_chunk_parser {
- ELCP_HEX,
- ELCP_CR,
- ELCP_CONTENT,
- ELCP_POST_CR,
- ELCP_POST_LF,
-};
-#endif
-
-enum lws_parse_urldecode_results {
- LPUR_CONTINUE,
- LPUR_SWALLOW,
- LPUR_FORBID,
- LPUR_EXCESSIVE,
-};
-
-enum lws_check_basic_auth_results {
- LCBA_CONTINUE,
- LCBA_FAILED_AUTH,
- LCBA_END_TRANSACTION,
-};
-
-enum lws_check_basic_auth_results
-lws_check_basic_auth(struct lws *wsi, const char *basic_auth_login_file);
-
-int
-lws_unauthorised_basic_auth(struct lws *wsi);
-
-int
-lws_read_h1(struct lws *wsi, unsigned char *buf, lws_filepos_t len);
-
-void
-_lws_header_table_reset(struct allocated_headers *ah);
-
-LWS_EXTERN int
-_lws_destroy_ah(struct lws_context_per_thread *pt, struct allocated_headers *ah);
-
-int
-lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit,
- char *uri_ptr, char ws);
-
-typedef struct lws_sorted_usec_list lws_sorted_usec_list_t;
-
-void
-lws_sul_http_ah_lifecheck(lws_sorted_usec_list_t *sul);
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
/*
* Produce Apache-compatible log string for wsi, like this:
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
#if defined(LWS_WITH_MINIZ)
#include <miniz.h>
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
#ifndef _WIN32
/* this is needed for Travis CI */
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
#define LWS_MAX_ELEM_NAME 32
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
static const unsigned char lextable[] = {
-#if defined(LWS_AMAZON_RTOS) || defined(LWS_AMAZON_LINUX)
- #include "roles/http/lextable.h"
-#else
- #include "../lextable.h"
-#endif
+ #include "lextable.h"
};
#define FAIL_CHAR 0x08
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
/*
* RFC7233 examples
-#include "core/private.h"
+#include "private-lib-core.h"
#if defined(LWS_WITH_HUBBUB)
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
const char * const method_names[] = {
"GET", "POST", "OPTIONS", "PUT", "PATCH", "DELETE", "CONNECT", "HEAD",
* MA 02110-1301 USA
*/
-#include <core/private.h>
+#include <private-lib-core.h>
static int
rops_handle_POLLIN_listen(struct lws_context_per_thread *pt, struct lws *wsi,
* MA 02110-1301 USA
*/
-#include <core/private.h>
+#include <private-lib-core.h>
static int
rops_handle_POLLIN_pipe(struct lws_context_per_thread *pt, struct lws *wsi,
--- /dev/null
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010 - 2018 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
+ *
+ * This is included from core/private.h
+ */
+
+typedef uint32_t lws_wsi_state_t;
+
+/*
+ * The wsi->role_ops pointer decides almost everything about what role the wsi
+ * will play, h2, raw, ws, etc.
+ *
+ * However there are a few additional flags needed that vary, such as if the
+ * role is a client or server side, if it has that concept. And the connection
+ * fulfilling the role, has a separate dynamic state.
+ *
+ * 31 16 15 0
+ * [ role flags ] [ state ]
+ *
+ * The role flags part is generally invariant for the lifetime of the wsi,
+ * although it can change if the connection role itself does, eg, if the
+ * connection upgrades from H1 -> WS1 the role flags may be changed at that
+ * point.
+ *
+ * The state part reflects the dynamic connection state, and the states are
+ * reused between roles.
+ *
+ * None of the internal role or state representations are made available outside
+ * of lws internals. Even for lws internals, if you add stuff here, please keep
+ * the constants inside this header only by adding necessary helpers here and
+ * use the helpers in the actual code. This is to ease any future refactors.
+ *
+ * Notice LWSIFR_ENCAP means we have a parent wsi that actually carries our
+ * data as a stream inside a different protocol.
+ */
+
+#define _RS 16
+
+#define LWSIFR_CLIENT (0x1000 << _RS) /* client side */
+#define LWSIFR_SERVER (0x2000 << _RS) /* server side */
+
+#define LWSIFR_P_ENCAP_H2 (0x0100 << _RS) /* we are encapsulated by h2 */
+
+enum lwsi_role {
+ LWSI_ROLE_MASK = (0xffff << _RS),
+ LWSI_ROLE_ENCAP_MASK = (0x0f00 << _RS),
+};
+
+#define lwsi_role(wsi) (wsi->wsistate & LWSI_ROLE_MASK)
+#if !defined (_DEBUG)
+#define lwsi_set_role(wsi, role) wsi->wsistate = \
+ (wsi->wsistate & (~LWSI_ROLE_MASK)) | role
+#else
+void lwsi_set_role(struct lws *wsi, lws_wsi_state_t role);
+#endif
+
+#define lwsi_role_client(wsi) (!!(wsi->wsistate & LWSIFR_CLIENT))
+#define lwsi_role_server(wsi) (!!(wsi->wsistate & LWSIFR_SERVER))
+#define lwsi_role_h2_ENCAPSULATION(wsi) \
+ ((wsi->wsistate & LWSI_ROLE_ENCAP_MASK) == LWSIFR_P_ENCAP_H2)
+
+/* Pollout wants a callback in this state */
+#define LWSIFS_POCB (0x100)
+/* Before any protocol connection was established */
+#define LWSIFS_NOT_EST (0x200)
+
+enum lwsi_state {
+
+ /* Phase 1: pre-transport */
+
+ LRS_UNCONNECTED = LWSIFS_NOT_EST | 0,
+ LRS_WAITING_CONNECT = LWSIFS_NOT_EST | 1,
+
+ /* Phase 2: establishing intermediaries on top of transport */
+
+ LRS_WAITING_PROXY_REPLY = LWSIFS_NOT_EST | 2,
+ LRS_WAITING_SSL = LWSIFS_NOT_EST | 3,
+ LRS_WAITING_SOCKS_GREETING_REPLY = LWSIFS_NOT_EST | 4,
+ LRS_WAITING_SOCKS_CONNECT_REPLY = LWSIFS_NOT_EST | 5,
+ LRS_WAITING_SOCKS_AUTH_REPLY = LWSIFS_NOT_EST | 6,
+
+ /* Phase 3: establishing tls tunnel */
+
+ LRS_SSL_INIT = LWSIFS_NOT_EST | 7,
+ LRS_SSL_ACK_PENDING = LWSIFS_NOT_EST | 8,
+ LRS_PRE_WS_SERVING_ACCEPT = LWSIFS_NOT_EST | 9,
+
+ /* Phase 4: connected */
+
+ LRS_WAITING_SERVER_REPLY = LWSIFS_NOT_EST | 10,
+ LRS_H2_AWAIT_PREFACE = LWSIFS_NOT_EST | 11,
+ LRS_H2_AWAIT_SETTINGS = LWSIFS_NOT_EST |
+ LWSIFS_POCB | 12,
+
+ /* Phase 5: protocol logically established */
+
+ LRS_H2_CLIENT_SEND_SETTINGS = LWSIFS_POCB | 13,
+ LRS_H2_WAITING_TO_SEND_HEADERS = LWSIFS_POCB | 14,
+ LRS_DEFERRING_ACTION = LWSIFS_POCB | 15,
+ LRS_IDLING = 16,
+ LRS_H1C_ISSUE_HANDSHAKE = 17,
+ LRS_H1C_ISSUE_HANDSHAKE2 = 18,
+ LRS_ISSUE_HTTP_BODY = 19,
+ LRS_ISSUING_FILE = 20,
+ LRS_HEADERS = 21,
+ LRS_BODY = 22,
+ LRS_DISCARD_BODY = 31,
+ LRS_ESTABLISHED = LWSIFS_POCB | 23,
+ /* we are established, but we have embarked on serving a single
+ * transaction. Other transaction input may be pending, but we will
+ * not service it while we are busy dealing with the current
+ * transaction.
+ *
+ * When we complete the current transaction, we would reset our state
+ * back to ESTABLISHED and start to process the next transaction.
+ */
+ LRS_DOING_TRANSACTION = LWSIFS_POCB | 24,
+
+ /* Phase 6: finishing */
+
+ LRS_WAITING_TO_SEND_CLOSE = LWSIFS_POCB | 25,
+ LRS_RETURNED_CLOSE = LWSIFS_POCB | 26,
+ LRS_AWAITING_CLOSE_ACK = LWSIFS_POCB | 27,
+ LRS_FLUSHING_BEFORE_CLOSE = LWSIFS_POCB | 28,
+ LRS_SHUTDOWN = 29,
+
+ /* Phase 7: dead */
+
+ LRS_DEAD_SOCKET = 30,
+
+ LRS_MASK = 0xffff
+};
+
+#define lwsi_state(wsi) ((enum lwsi_state)(wsi->wsistate & LRS_MASK))
+#define lwsi_state_PRE_CLOSE(wsi) \
+ ((enum lwsi_state)(wsi->wsistate_pre_close & LRS_MASK))
+#define lwsi_state_est(wsi) (!(wsi->wsistate & LWSIFS_NOT_EST))
+#define lwsi_state_est_PRE_CLOSE(wsi) \
+ (!(wsi->wsistate_pre_close & LWSIFS_NOT_EST))
+#define lwsi_state_can_handle_POLLOUT(wsi) (wsi->wsistate & LWSIFS_POCB)
+#if !defined (_DEBUG)
+#define lwsi_set_state(wsi, lrs) wsi->wsistate = \
+ (wsi->wsistate & (~LRS_MASK)) | lrs
+#else
+void lwsi_set_state(struct lws *wsi, lws_wsi_state_t lrs);
+#endif
+
+#define _LWS_ADOPT_FINISH (1 << 24)
+
+/*
+ * internal role-specific ops
+ */
+struct lws_context_per_thread;
+struct lws_role_ops {
+ const char *name;
+ const char *alpn;
+ /*
+ * After http headers have parsed, this is the last chance for a role
+ * to upgrade the connection to something else using the headers.
+ * ws-over-h2 is upgraded from h2 like this.
+ */
+ int (*check_upgrades)(struct lws *wsi);
+ /* role-specific context init during context creation */
+ int (*init_context)(struct lws_context *context,
+ const struct lws_context_creation_info *info);
+ /* role-specific per-vhost init during vhost creation */
+ int (*init_vhost)(struct lws_vhost *vh,
+ const struct lws_context_creation_info *info);
+ /* role-specific per-vhost destructor during vhost destroy */
+ int (*destroy_vhost)(struct lws_vhost *vh);
+ /* generic 1Hz callback for the role itself */
+ int (*periodic_checks)(struct lws_context *context, int tsi,
+ time_t now);
+ /* chance for the role to force POLLIN without network activity */
+ int (*service_flag_pending)(struct lws_context *context, int tsi);
+ /* an fd using this role has POLLIN signalled */
+ int (*handle_POLLIN)(struct lws_context_per_thread *pt, struct lws *wsi,
+ struct lws_pollfd *pollfd);
+ /* an fd using the role wanted a POLLOUT callback and now has it */
+ int (*handle_POLLOUT)(struct lws *wsi);
+ /* perform user pollout */
+ int (*perform_user_POLLOUT)(struct lws *wsi);
+ /* do effective callback on writeable */
+ int (*callback_on_writable)(struct lws *wsi);
+ /* connection-specific tx credit in bytes */
+ lws_fileofs_t (*tx_credit)(struct lws *wsi);
+ /* role-specific write formatting */
+ int (*write_role_protocol)(struct lws *wsi, unsigned char *buf,
+ size_t len, enum lws_write_protocol *wp);
+
+ /* get encapsulation parent */
+ struct lws * (*encapsulation_parent)(struct lws *wsi);
+
+ /* role-specific destructor */
+ int (*alpn_negotiated)(struct lws *wsi, const char *alpn);
+
+ /* chance for the role to handle close in the protocol */
+ int (*close_via_role_protocol)(struct lws *wsi,
+ enum lws_close_status reason);
+ /* role-specific close processing */
+ int (*close_role)(struct lws_context_per_thread *pt, struct lws *wsi);
+ /* role-specific connection close processing */
+ int (*close_kill_connection)(struct lws *wsi,
+ enum lws_close_status reason);
+ /* role-specific destructor */
+ int (*destroy_role)(struct lws *wsi);
+
+ /* role-specific socket-adopt */
+ int (*adoption_bind)(struct lws *wsi, int type, const char *prot);
+ /* role-specific client-bind:
+ * ret 1 = bound, 0 = not bound, -1 = fail out
+ * i may be NULL, indicating client_bind is being called after
+ * a successful bind earlier, to finalize the binding. In that
+ * case ret 0 = OK, 1 = fail, wsi needs freeing, -1 = fail, wsi freed */
+ int (*client_bind)(struct lws *wsi,
+ const struct lws_client_connect_info *i);
+
+ /*
+ * the callback reasons for adoption for client, server
+ * (just client applies if no concept of client or server)
+ */
+ uint16_t adoption_cb[2];
+ /*
+ * the callback reasons for adoption for client, server
+ * (just client applies if no concept of client or server)
+ */
+ uint16_t rx_cb[2];
+ /*
+ * the callback reasons for WRITEABLE for client, server
+ * (just client applies if no concept of client or server)
+ */
+ uint16_t writeable_cb[2];
+ /*
+ * the callback reasons for CLOSE for client, server
+ * (just client applies if no concept of client or server)
+ */
+ uint16_t close_cb[2];
+ /*
+ * the callback reasons for protocol bind for client, server
+ * (just client applies if no concept of client or server)
+ */
+ uint16_t protocol_bind_cb[2];
+ /*
+ * the callback reasons for protocol unbind for client, server
+ * (just client applies if no concept of client or server)
+ */
+ uint16_t protocol_unbind_cb[2];
+
+ unsigned int file_handle:1; /* role operates on files not sockets */
+};
+
+/* core roles */
+extern struct lws_role_ops role_ops_raw_skt, role_ops_raw_file, role_ops_listen,
+ role_ops_pipe;
+
+/* bring in role private declarations */
+
+#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
+ #include "private-lib-roles-http.h"
+#else
+ #define lwsi_role_http(wsi) (0)
+#endif
+
+#if defined(LWS_ROLE_H1)
+ #include "private-lib-roles-h1.h"
+#else
+ #define lwsi_role_h1(wsi) (0)
+#endif
+
+#if defined(LWS_ROLE_H2)
+ #include "private-lib-roles-h2.h"
+#else
+ #define lwsi_role_h2(wsi) (0)
+#endif
+
+#if defined(LWS_ROLE_WS)
+ #include "private-lib-roles-ws.h"
+#else
+ #define lwsi_role_ws(wsi) (0)
+#endif
+
+#if defined(LWS_ROLE_CGI)
+ #include "private-lib-roles-cgi.h"
+#else
+ #define lwsi_role_cgi(wsi) (0)
+#endif
+
+#if defined(LWS_ROLE_DBUS)
+ #include "private-lib-roles-dbus.h"
+#else
+ #define lwsi_role_dbus(wsi) (0)
+#endif
+
+#if defined(LWS_ROLE_RAW_PROXY)
+ #include "private-lib-roles-raw-proxy.h"
+#else
+ #define lwsi_role_raw_proxy(wsi) (0)
+#endif
+
+enum {
+ LWS_HP_RET_BAIL_OK,
+ LWS_HP_RET_BAIL_DIE,
+ LWS_HP_RET_USER_SERVICE,
+
+ LWS_HPI_RET_WSI_ALREADY_DIED, /* we closed it */
+ LWS_HPI_RET_HANDLED, /* no probs */
+ LWS_HPI_RET_PLEASE_CLOSE_ME, /* close it for us */
+
+ LWS_UPG_RET_DONE,
+ LWS_UPG_RET_CONTINUE,
+ LWS_UPG_RET_BAIL
+};
+
+int
+lws_role_call_adoption_bind(struct lws *wsi, int type, const char *prot);
+
+struct lws *
+lws_client_connect_3(struct lws *wsi, struct lws *wsi_piggyback, ssize_t plen);
+++ /dev/null
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 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
- *
- * This is included from core/private.h
- */
-
-typedef uint32_t lws_wsi_state_t;
-
-/*
- * The wsi->role_ops pointer decides almost everything about what role the wsi
- * will play, h2, raw, ws, etc.
- *
- * However there are a few additional flags needed that vary, such as if the
- * role is a client or server side, if it has that concept. And the connection
- * fulfilling the role, has a separate dynamic state.
- *
- * 31 16 15 0
- * [ role flags ] [ state ]
- *
- * The role flags part is generally invariant for the lifetime of the wsi,
- * although it can change if the connection role itself does, eg, if the
- * connection upgrades from H1 -> WS1 the role flags may be changed at that
- * point.
- *
- * The state part reflects the dynamic connection state, and the states are
- * reused between roles.
- *
- * None of the internal role or state representations are made available outside
- * of lws internals. Even for lws internals, if you add stuff here, please keep
- * the constants inside this header only by adding necessary helpers here and
- * use the helpers in the actual code. This is to ease any future refactors.
- *
- * Notice LWSIFR_ENCAP means we have a parent wsi that actually carries our
- * data as a stream inside a different protocol.
- */
-
-#define _RS 16
-
-#define LWSIFR_CLIENT (0x1000 << _RS) /* client side */
-#define LWSIFR_SERVER (0x2000 << _RS) /* server side */
-
-#define LWSIFR_P_ENCAP_H2 (0x0100 << _RS) /* we are encapsulated by h2 */
-
-enum lwsi_role {
- LWSI_ROLE_MASK = (0xffff << _RS),
- LWSI_ROLE_ENCAP_MASK = (0x0f00 << _RS),
-};
-
-#define lwsi_role(wsi) (wsi->wsistate & LWSI_ROLE_MASK)
-#if !defined (_DEBUG)
-#define lwsi_set_role(wsi, role) wsi->wsistate = \
- (wsi->wsistate & (~LWSI_ROLE_MASK)) | role
-#else
-void lwsi_set_role(struct lws *wsi, lws_wsi_state_t role);
-#endif
-
-#define lwsi_role_client(wsi) (!!(wsi->wsistate & LWSIFR_CLIENT))
-#define lwsi_role_server(wsi) (!!(wsi->wsistate & LWSIFR_SERVER))
-#define lwsi_role_h2_ENCAPSULATION(wsi) \
- ((wsi->wsistate & LWSI_ROLE_ENCAP_MASK) == LWSIFR_P_ENCAP_H2)
-
-/* Pollout wants a callback in this state */
-#define LWSIFS_POCB (0x100)
-/* Before any protocol connection was established */
-#define LWSIFS_NOT_EST (0x200)
-
-enum lwsi_state {
-
- /* Phase 1: pre-transport */
-
- LRS_UNCONNECTED = LWSIFS_NOT_EST | 0,
- LRS_WAITING_CONNECT = LWSIFS_NOT_EST | 1,
-
- /* Phase 2: establishing intermediaries on top of transport */
-
- LRS_WAITING_PROXY_REPLY = LWSIFS_NOT_EST | 2,
- LRS_WAITING_SSL = LWSIFS_NOT_EST | 3,
- LRS_WAITING_SOCKS_GREETING_REPLY = LWSIFS_NOT_EST | 4,
- LRS_WAITING_SOCKS_CONNECT_REPLY = LWSIFS_NOT_EST | 5,
- LRS_WAITING_SOCKS_AUTH_REPLY = LWSIFS_NOT_EST | 6,
-
- /* Phase 3: establishing tls tunnel */
-
- LRS_SSL_INIT = LWSIFS_NOT_EST | 7,
- LRS_SSL_ACK_PENDING = LWSIFS_NOT_EST | 8,
- LRS_PRE_WS_SERVING_ACCEPT = LWSIFS_NOT_EST | 9,
-
- /* Phase 4: connected */
-
- LRS_WAITING_SERVER_REPLY = LWSIFS_NOT_EST | 10,
- LRS_H2_AWAIT_PREFACE = LWSIFS_NOT_EST | 11,
- LRS_H2_AWAIT_SETTINGS = LWSIFS_NOT_EST |
- LWSIFS_POCB | 12,
-
- /* Phase 5: protocol logically established */
-
- LRS_H2_CLIENT_SEND_SETTINGS = LWSIFS_POCB | 13,
- LRS_H2_WAITING_TO_SEND_HEADERS = LWSIFS_POCB | 14,
- LRS_DEFERRING_ACTION = LWSIFS_POCB | 15,
- LRS_IDLING = 16,
- LRS_H1C_ISSUE_HANDSHAKE = 17,
- LRS_H1C_ISSUE_HANDSHAKE2 = 18,
- LRS_ISSUE_HTTP_BODY = 19,
- LRS_ISSUING_FILE = 20,
- LRS_HEADERS = 21,
- LRS_BODY = 22,
- LRS_DISCARD_BODY = 31,
- LRS_ESTABLISHED = LWSIFS_POCB | 23,
- /* we are established, but we have embarked on serving a single
- * transaction. Other transaction input may be pending, but we will
- * not service it while we are busy dealing with the current
- * transaction.
- *
- * When we complete the current transaction, we would reset our state
- * back to ESTABLISHED and start to process the next transaction.
- */
- LRS_DOING_TRANSACTION = LWSIFS_POCB | 24,
-
- /* Phase 6: finishing */
-
- LRS_WAITING_TO_SEND_CLOSE = LWSIFS_POCB | 25,
- LRS_RETURNED_CLOSE = LWSIFS_POCB | 26,
- LRS_AWAITING_CLOSE_ACK = LWSIFS_POCB | 27,
- LRS_FLUSHING_BEFORE_CLOSE = LWSIFS_POCB | 28,
- LRS_SHUTDOWN = 29,
-
- /* Phase 7: dead */
-
- LRS_DEAD_SOCKET = 30,
-
- LRS_MASK = 0xffff
-};
-
-#define lwsi_state(wsi) ((enum lwsi_state)(wsi->wsistate & LRS_MASK))
-#define lwsi_state_PRE_CLOSE(wsi) \
- ((enum lwsi_state)(wsi->wsistate_pre_close & LRS_MASK))
-#define lwsi_state_est(wsi) (!(wsi->wsistate & LWSIFS_NOT_EST))
-#define lwsi_state_est_PRE_CLOSE(wsi) \
- (!(wsi->wsistate_pre_close & LWSIFS_NOT_EST))
-#define lwsi_state_can_handle_POLLOUT(wsi) (wsi->wsistate & LWSIFS_POCB)
-#if !defined (_DEBUG)
-#define lwsi_set_state(wsi, lrs) wsi->wsistate = \
- (wsi->wsistate & (~LRS_MASK)) | lrs
-#else
-void lwsi_set_state(struct lws *wsi, lws_wsi_state_t lrs);
-#endif
-
-#define _LWS_ADOPT_FINISH (1 << 24)
-
-/*
- * internal role-specific ops
- */
-struct lws_context_per_thread;
-struct lws_role_ops {
- const char *name;
- const char *alpn;
- /*
- * After http headers have parsed, this is the last chance for a role
- * to upgrade the connection to something else using the headers.
- * ws-over-h2 is upgraded from h2 like this.
- */
- int (*check_upgrades)(struct lws *wsi);
- /* role-specific context init during context creation */
- int (*init_context)(struct lws_context *context,
- const struct lws_context_creation_info *info);
- /* role-specific per-vhost init during vhost creation */
- int (*init_vhost)(struct lws_vhost *vh,
- const struct lws_context_creation_info *info);
- /* role-specific per-vhost destructor during vhost destroy */
- int (*destroy_vhost)(struct lws_vhost *vh);
- /* generic 1Hz callback for the role itself */
- int (*periodic_checks)(struct lws_context *context, int tsi,
- time_t now);
- /* chance for the role to force POLLIN without network activity */
- int (*service_flag_pending)(struct lws_context *context, int tsi);
- /* an fd using this role has POLLIN signalled */
- int (*handle_POLLIN)(struct lws_context_per_thread *pt, struct lws *wsi,
- struct lws_pollfd *pollfd);
- /* an fd using the role wanted a POLLOUT callback and now has it */
- int (*handle_POLLOUT)(struct lws *wsi);
- /* perform user pollout */
- int (*perform_user_POLLOUT)(struct lws *wsi);
- /* do effective callback on writeable */
- int (*callback_on_writable)(struct lws *wsi);
- /* connection-specific tx credit in bytes */
- lws_fileofs_t (*tx_credit)(struct lws *wsi);
- /* role-specific write formatting */
- int (*write_role_protocol)(struct lws *wsi, unsigned char *buf,
- size_t len, enum lws_write_protocol *wp);
-
- /* get encapsulation parent */
- struct lws * (*encapsulation_parent)(struct lws *wsi);
-
- /* role-specific destructor */
- int (*alpn_negotiated)(struct lws *wsi, const char *alpn);
-
- /* chance for the role to handle close in the protocol */
- int (*close_via_role_protocol)(struct lws *wsi,
- enum lws_close_status reason);
- /* role-specific close processing */
- int (*close_role)(struct lws_context_per_thread *pt, struct lws *wsi);
- /* role-specific connection close processing */
- int (*close_kill_connection)(struct lws *wsi,
- enum lws_close_status reason);
- /* role-specific destructor */
- int (*destroy_role)(struct lws *wsi);
-
- /* role-specific socket-adopt */
- int (*adoption_bind)(struct lws *wsi, int type, const char *prot);
- /* role-specific client-bind:
- * ret 1 = bound, 0 = not bound, -1 = fail out
- * i may be NULL, indicating client_bind is being called after
- * a successful bind earlier, to finalize the binding. In that
- * case ret 0 = OK, 1 = fail, wsi needs freeing, -1 = fail, wsi freed */
- int (*client_bind)(struct lws *wsi,
- const struct lws_client_connect_info *i);
-
- /*
- * the callback reasons for adoption for client, server
- * (just client applies if no concept of client or server)
- */
- uint16_t adoption_cb[2];
- /*
- * the callback reasons for adoption for client, server
- * (just client applies if no concept of client or server)
- */
- uint16_t rx_cb[2];
- /*
- * the callback reasons for WRITEABLE for client, server
- * (just client applies if no concept of client or server)
- */
- uint16_t writeable_cb[2];
- /*
- * the callback reasons for CLOSE for client, server
- * (just client applies if no concept of client or server)
- */
- uint16_t close_cb[2];
- /*
- * the callback reasons for protocol bind for client, server
- * (just client applies if no concept of client or server)
- */
- uint16_t protocol_bind_cb[2];
- /*
- * the callback reasons for protocol unbind for client, server
- * (just client applies if no concept of client or server)
- */
- uint16_t protocol_unbind_cb[2];
-
- unsigned int file_handle:1; /* role operates on files not sockets */
-};
-
-/* core roles */
-extern struct lws_role_ops role_ops_raw_skt, role_ops_raw_file, role_ops_listen,
- role_ops_pipe;
-
-/* bring in role private declarations */
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- #include "roles/http/private.h"
-#else
- #define lwsi_role_http(wsi) (0)
-#endif
-
-#if defined(LWS_ROLE_H1)
- #include "roles/h1/private.h"
-#else
- #define lwsi_role_h1(wsi) (0)
-#endif
-
-#if defined(LWS_ROLE_H2)
- #include "roles/h2/private.h"
-#else
- #define lwsi_role_h2(wsi) (0)
-#endif
-
-#if defined(LWS_ROLE_WS)
- #include "roles/ws/private.h"
-#else
- #define lwsi_role_ws(wsi) (0)
-#endif
-
-#if defined(LWS_ROLE_CGI)
- #include "roles/cgi/private.h"
-#else
- #define lwsi_role_cgi(wsi) (0)
-#endif
-
-#if defined(LWS_ROLE_DBUS)
- #include "roles/dbus/private.h"
-#else
- #define lwsi_role_dbus(wsi) (0)
-#endif
-
-#if defined(LWS_ROLE_RAW_PROXY)
- #include "roles/raw-proxy/private.h"
-#else
- #define lwsi_role_raw_proxy(wsi) (0)
-#endif
-
-enum {
- LWS_HP_RET_BAIL_OK,
- LWS_HP_RET_BAIL_DIE,
- LWS_HP_RET_USER_SERVICE,
-
- LWS_HPI_RET_WSI_ALREADY_DIED, /* we closed it */
- LWS_HPI_RET_HANDLED, /* no probs */
- LWS_HPI_RET_PLEASE_CLOSE_ME, /* close it for us */
-
- LWS_UPG_RET_DONE,
- LWS_UPG_RET_CONTINUE,
- LWS_UPG_RET_BAIL
-};
-
-int
-lws_role_call_adoption_bind(struct lws *wsi, int type, const char *prot);
-
-struct lws *
-lws_client_connect_3(struct lws *wsi, struct lws *wsi_piggyback, ssize_t plen);
* MA 02110-1301 USA
*/
-#include <core/private.h>
+#include <private-lib-core.h>
static int
rops_handle_POLLIN_raw_file(struct lws_context_per_thread *pt, struct lws *wsi,
* MA 02110-1301 USA
*/
-#include <core/private.h>
+#include <private-lib-core.h>
static int
rops_handle_POLLIN_raw_proxy(struct lws_context_per_thread *pt, struct lws *wsi,
--- /dev/null
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010 - 2018 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
+ *
+ * This is included from private-lib-core.h if LWS_ROLE_RAW_PROXY
+ */
+
+extern struct lws_role_ops role_ops_raw_proxy;
+
+#define lwsi_role_raw_proxy(wsi) (wsi->role_ops == &role_ops_raw_proxy)
+
+#if 0
+struct lws_vhost_role_ws {
+ const struct lws_extension *extensions;
+};
+
+struct lws_pt_role_ws {
+ struct lws *rx_draining_ext_list;
+ struct lws *tx_draining_ext_list;
+};
+
+struct _lws_raw_proxy_related {
+ struct lws *wsi_onward;
+};
+#endif
+++ /dev/null
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 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
- *
- * This is included from core/private.h if LWS_ROLE_RAW_PROXY
- */
-
-extern struct lws_role_ops role_ops_raw_proxy;
-
-#define lwsi_role_raw_proxy(wsi) (wsi->role_ops == &role_ops_raw_proxy)
-
-#if 0
-struct lws_vhost_role_ws {
- const struct lws_extension *extensions;
-};
-
-struct lws_pt_role_ws {
- struct lws *rx_draining_ext_list;
- struct lws *tx_draining_ext_list;
-};
-
-struct _lws_raw_proxy_related {
- struct lws *wsi_onward;
-};
-#endif
* MA 02110-1301 USA
*/
-#include <core/private.h>
+#include <private-lib-core.h>
static int
rops_handle_POLLIN_raw_skt(struct lws_context_per_thread *pt, struct lws *wsi,
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
/*
* parsers.c: lws_ws_rx_sm() needs to be roughly kept in
* MA 02110-1301 USA
*/
-#include <core/private.h>
+#include <private-lib-core.h>
/*
* In-place str to lower case
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
#include "extension-permessage-deflate.h"
#include <stdio.h>
#include <string.h>
-#include "core/private.h"
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "private-lib-core.h"
#include "extension-permessage-deflate.h"
* MA 02110-1301 USA
*/
-#include <core/private.h>
+#include <private-lib-core.h>
#define LWS_CPYAPP(ptr, str) { strcpy(ptr, str); ptr += strlen(str); }
--- /dev/null
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010 - 2018 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
+ *
+ * This is included from private-lib-core.h if LWS_ROLE_WS
+ */
+
+extern struct lws_role_ops role_ops_ws;
+
+#define lwsi_role_ws(wsi) (wsi->role_ops == &role_ops_ws)
+
+enum lws_rx_parse_state {
+ LWS_RXPS_NEW,
+
+ LWS_RXPS_04_mask_1,
+ LWS_RXPS_04_mask_2,
+ LWS_RXPS_04_mask_3,
+
+ LWS_RXPS_04_FRAME_HDR_1,
+ LWS_RXPS_04_FRAME_HDR_LEN,
+ LWS_RXPS_04_FRAME_HDR_LEN16_2,
+ LWS_RXPS_04_FRAME_HDR_LEN16_1,
+ LWS_RXPS_04_FRAME_HDR_LEN64_8,
+ LWS_RXPS_04_FRAME_HDR_LEN64_7,
+ LWS_RXPS_04_FRAME_HDR_LEN64_6,
+ LWS_RXPS_04_FRAME_HDR_LEN64_5,
+ LWS_RXPS_04_FRAME_HDR_LEN64_4,
+ LWS_RXPS_04_FRAME_HDR_LEN64_3,
+ LWS_RXPS_04_FRAME_HDR_LEN64_2,
+ LWS_RXPS_04_FRAME_HDR_LEN64_1,
+
+ LWS_RXPS_07_COLLECT_FRAME_KEY_1,
+ LWS_RXPS_07_COLLECT_FRAME_KEY_2,
+ LWS_RXPS_07_COLLECT_FRAME_KEY_3,
+ LWS_RXPS_07_COLLECT_FRAME_KEY_4,
+
+ LWS_RXPS_WS_FRAME_PAYLOAD
+};
+
+enum lws_websocket_opcodes_07 {
+ LWSWSOPC_CONTINUATION = 0,
+ LWSWSOPC_TEXT_FRAME = 1,
+ LWSWSOPC_BINARY_FRAME = 2,
+
+ LWSWSOPC_NOSPEC__MUX = 7,
+
+ /* control extensions 8+ */
+
+ LWSWSOPC_CLOSE = 8,
+ LWSWSOPC_PING = 9,
+ LWSWSOPC_PONG = 0xa,
+};
+
+/* this is not usable directly by user code any more, lws_close_reason() */
+#define LWS_WRITE_CLOSE 4
+
+#define ALREADY_PROCESSED_IGNORE_CHAR 1
+#define ALREADY_PROCESSED_NO_CB 2
+
+#if !defined(LWS_WITHOUT_EXTENSIONS)
+struct lws_vhost_role_ws {
+ const struct lws_extension *extensions;
+};
+
+struct lws_pt_role_ws {
+ struct lws *rx_draining_ext_list;
+ struct lws *tx_draining_ext_list;
+};
+#endif
+
+struct _lws_websocket_related {
+ unsigned char *rx_ubuf;
+#if !defined(LWS_WITHOUT_EXTENSIONS)
+ const struct lws_extension *active_extensions[LWS_MAX_EXTENSIONS_ACTIVE];
+ void *act_ext_user[LWS_MAX_EXTENSIONS_ACTIVE];
+ struct lws *rx_draining_ext_list;
+ struct lws *tx_draining_ext_list;
+#endif
+
+#if defined(LWS_WITH_HTTP_PROXY)
+ struct lws_dll2_owner proxy_owner;
+ char actual_protocol[16];
+ size_t proxy_buffered;
+#endif
+
+ /* Also used for close content... control opcode == < 128 */
+ uint8_t ping_payload_buf[128 - 3 + LWS_PRE];
+ uint8_t mask[4];
+
+ size_t rx_packet_length;
+ uint32_t rx_ubuf_head;
+ uint32_t rx_ubuf_alloc;
+
+ uint8_t ping_payload_len;
+ uint8_t mask_idx;
+ uint8_t opcode;
+ uint8_t rsv;
+ uint8_t rsv_first_msg;
+ /* zero if no info, or length including 2-byte close code */
+ uint8_t close_in_ping_buffer_len;
+ uint8_t utf8;
+ uint8_t stashed_write_type;
+ uint8_t tx_draining_stashed_wp;
+ uint8_t ietf_spec_revision;
+
+ unsigned int final:1;
+ unsigned int frame_is_binary:1;
+ unsigned int all_zero_nonce:1;
+ unsigned int this_frame_masked:1;
+ unsigned int inside_frame:1; /* next write will be more of frame */
+ unsigned int clean_buffer:1; /* buffer not rewritten by extension */
+ unsigned int payload_is_close:1; /* process as PONG, but it is close */
+ unsigned int ping_pending_flag:1;
+ unsigned int continuation_possible:1;
+ unsigned int owed_a_fin:1;
+ unsigned int check_utf8:1;
+ unsigned int defeat_check_utf8:1;
+ unsigned int stashed_write_pending:1;
+ unsigned int send_check_ping:1;
+ unsigned int first_fragment:1;
+ unsigned int peer_has_sent_close:1;
+ unsigned int await_pong;
+#if !defined(LWS_WITHOUT_EXTENSIONS)
+ unsigned int extension_data_pending:1;
+ unsigned int rx_draining_ext:1;
+ unsigned int tx_draining_ext:1;
+ unsigned int pmd_trailer_application:1;
+
+ uint8_t count_act_ext;
+#endif
+};
+
+/*
+ * we need to separately track what's happening with both compressed rx in
+ * and with inflated rx out that will be passed to the user code
+ */
+
+struct lws_ext_pm_deflate_rx_ebufs {
+ struct lws_tokens eb_in;
+ struct lws_tokens eb_out;
+};
+
+int
+lws_ws_handshake_client(struct lws *wsi, unsigned char **buf, size_t len);
+
+#if !defined(LWS_WITHOUT_EXTENSIONS)
+LWS_VISIBLE void
+lws_context_init_extensions(const struct lws_context_creation_info *info,
+ struct lws_context *context);
+LWS_EXTERN int
+lws_any_extension_handled(struct lws *wsi, enum lws_extension_callback_reasons r,
+ void *v, size_t len);
+
+LWS_EXTERN int
+lws_ext_cb_active(struct lws *wsi, int reason, void *buf, int len);
+LWS_EXTERN int
+lws_ext_cb_all_exts(struct lws_context *context, struct lws *wsi, int reason,
+ void *arg, int len);
+#endif
+
+int
+handshake_0405(struct lws_context *context, struct lws *wsi);
+int
+lws_process_ws_upgrade(struct lws *wsi);
+
+int
+lws_process_ws_upgrade2(struct lws *wsi);
+
+extern const struct lws_protocols lws_ws_proxy;
+
+int
+lws_server_init_wsi_for_ws(struct lws *wsi);
+
+void
+lws_sul_wsping_cb(lws_sorted_usec_list_t *sul);
+++ /dev/null
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 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
- *
- * This is included from core/private.h if LWS_ROLE_WS
- */
-
-extern struct lws_role_ops role_ops_ws;
-
-#define lwsi_role_ws(wsi) (wsi->role_ops == &role_ops_ws)
-
-enum lws_rx_parse_state {
- LWS_RXPS_NEW,
-
- LWS_RXPS_04_mask_1,
- LWS_RXPS_04_mask_2,
- LWS_RXPS_04_mask_3,
-
- LWS_RXPS_04_FRAME_HDR_1,
- LWS_RXPS_04_FRAME_HDR_LEN,
- LWS_RXPS_04_FRAME_HDR_LEN16_2,
- LWS_RXPS_04_FRAME_HDR_LEN16_1,
- LWS_RXPS_04_FRAME_HDR_LEN64_8,
- LWS_RXPS_04_FRAME_HDR_LEN64_7,
- LWS_RXPS_04_FRAME_HDR_LEN64_6,
- LWS_RXPS_04_FRAME_HDR_LEN64_5,
- LWS_RXPS_04_FRAME_HDR_LEN64_4,
- LWS_RXPS_04_FRAME_HDR_LEN64_3,
- LWS_RXPS_04_FRAME_HDR_LEN64_2,
- LWS_RXPS_04_FRAME_HDR_LEN64_1,
-
- LWS_RXPS_07_COLLECT_FRAME_KEY_1,
- LWS_RXPS_07_COLLECT_FRAME_KEY_2,
- LWS_RXPS_07_COLLECT_FRAME_KEY_3,
- LWS_RXPS_07_COLLECT_FRAME_KEY_4,
-
- LWS_RXPS_WS_FRAME_PAYLOAD
-};
-
-enum lws_websocket_opcodes_07 {
- LWSWSOPC_CONTINUATION = 0,
- LWSWSOPC_TEXT_FRAME = 1,
- LWSWSOPC_BINARY_FRAME = 2,
-
- LWSWSOPC_NOSPEC__MUX = 7,
-
- /* control extensions 8+ */
-
- LWSWSOPC_CLOSE = 8,
- LWSWSOPC_PING = 9,
- LWSWSOPC_PONG = 0xa,
-};
-
-/* this is not usable directly by user code any more, lws_close_reason() */
-#define LWS_WRITE_CLOSE 4
-
-#define ALREADY_PROCESSED_IGNORE_CHAR 1
-#define ALREADY_PROCESSED_NO_CB 2
-
-#if !defined(LWS_WITHOUT_EXTENSIONS)
-struct lws_vhost_role_ws {
- const struct lws_extension *extensions;
-};
-
-struct lws_pt_role_ws {
- struct lws *rx_draining_ext_list;
- struct lws *tx_draining_ext_list;
-};
-#endif
-
-struct _lws_websocket_related {
- unsigned char *rx_ubuf;
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- const struct lws_extension *active_extensions[LWS_MAX_EXTENSIONS_ACTIVE];
- void *act_ext_user[LWS_MAX_EXTENSIONS_ACTIVE];
- struct lws *rx_draining_ext_list;
- struct lws *tx_draining_ext_list;
-#endif
-
-#if defined(LWS_WITH_HTTP_PROXY)
- struct lws_dll2_owner proxy_owner;
- char actual_protocol[16];
- size_t proxy_buffered;
-#endif
-
- /* Also used for close content... control opcode == < 128 */
- uint8_t ping_payload_buf[128 - 3 + LWS_PRE];
- uint8_t mask[4];
-
- size_t rx_packet_length;
- uint32_t rx_ubuf_head;
- uint32_t rx_ubuf_alloc;
-
- uint8_t ping_payload_len;
- uint8_t mask_idx;
- uint8_t opcode;
- uint8_t rsv;
- uint8_t rsv_first_msg;
- /* zero if no info, or length including 2-byte close code */
- uint8_t close_in_ping_buffer_len;
- uint8_t utf8;
- uint8_t stashed_write_type;
- uint8_t tx_draining_stashed_wp;
- uint8_t ietf_spec_revision;
-
- unsigned int final:1;
- unsigned int frame_is_binary:1;
- unsigned int all_zero_nonce:1;
- unsigned int this_frame_masked:1;
- unsigned int inside_frame:1; /* next write will be more of frame */
- unsigned int clean_buffer:1; /* buffer not rewritten by extension */
- unsigned int payload_is_close:1; /* process as PONG, but it is close */
- unsigned int ping_pending_flag:1;
- unsigned int continuation_possible:1;
- unsigned int owed_a_fin:1;
- unsigned int check_utf8:1;
- unsigned int defeat_check_utf8:1;
- unsigned int stashed_write_pending:1;
- unsigned int send_check_ping:1;
- unsigned int first_fragment:1;
- unsigned int peer_has_sent_close:1;
- unsigned int await_pong;
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- unsigned int extension_data_pending:1;
- unsigned int rx_draining_ext:1;
- unsigned int tx_draining_ext:1;
- unsigned int pmd_trailer_application:1;
-
- uint8_t count_act_ext;
-#endif
-};
-
-/*
- * we need to separately track what's happening with both compressed rx in
- * and with inflated rx out that will be passed to the user code
- */
-
-struct lws_ext_pm_deflate_rx_ebufs {
- struct lws_tokens eb_in;
- struct lws_tokens eb_out;
-};
-
-int
-lws_ws_handshake_client(struct lws *wsi, unsigned char **buf, size_t len);
-
-#if !defined(LWS_WITHOUT_EXTENSIONS)
-LWS_VISIBLE void
-lws_context_init_extensions(const struct lws_context_creation_info *info,
- struct lws_context *context);
-LWS_EXTERN int
-lws_any_extension_handled(struct lws *wsi, enum lws_extension_callback_reasons r,
- void *v, size_t len);
-
-LWS_EXTERN int
-lws_ext_cb_active(struct lws *wsi, int reason, void *buf, int len);
-LWS_EXTERN int
-lws_ext_cb_all_exts(struct lws_context *context, struct lws *wsi, int reason,
- void *arg, int len);
-#endif
-
-int
-handshake_0405(struct lws_context *context, struct lws *wsi);
-int
-lws_process_ws_upgrade(struct lws *wsi);
-
-int
-lws_process_ws_upgrade2(struct lws *wsi);
-
-extern const struct lws_protocols lws_ws_proxy;
-
-int
-lws_server_init_wsi_for_ws(struct lws *wsi);
-
-void
-lws_sul_wsping_cb(lws_sorted_usec_list_t *sul);
* MA 02110-1301 USA
*/
-#include <core/private.h>
+#include <private-lib-core.h>
#define LWS_CPYAPP(ptr, str) { strcpy(ptr, str); ptr += strlen(str); }
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
-#include "core/private.h"
+
+#include "private-lib-core.h"
/*
* These came from RFC7518 (JSON Web Algorithms) Section 3
* lws_genec provides an EC abstraction api in lws that works the
* same whether you are using openssl or mbedtls crypto functions underneath.
*/
-#include "core/private.h"
+#include "private-lib-core.h"
const struct lws_ec_curves *
lws_genec_curve(const struct lws_ec_curves *table, const char *name)
* lws_genaes provides an abstraction api for AES in lws that works the
* same whether you are using openssl or mbedtls hash functions underneath.
*/
-#include "core/private.h"
-#include "../../jose/private.h"
+#include "private-lib-core.h"
+#include "../../jose/private-lib-jose.h"
static int operation_map[] = { MBEDTLS_AES_ENCRYPT, MBEDTLS_AES_DECRYPT };
* lws-gencrypto openssl-specific common code
*/
-#include "core/private.h"
-#include "tls/mbedtls/private.h"
+#include "private-lib-core.h"
+#include "private-lib-tls-mbedtls.h"
mbedtls_md_type_t
lws_gencrypto_mbedtls_hash_to_MD_TYPE(enum lws_genhash_types hash_type)
* lws_genec provides an EC abstraction api in lws that works the
* same whether you are using openssl or mbedtls crypto functions underneath.
*/
-#include "core/private.h"
-#include "tls/mbedtls/private.h"
+#include "private-lib-core.h"
+#include "private-lib-tls-mbedtls.h"
const struct lws_ec_curves lws_ec_curves[] = {
/*
* lws_genrsa provides an RSA abstraction api in lws that works the
* same whether you are using openssl or mbedtls crypto functions underneath.
*/
-#include "core/private.h"
-#include "tls/mbedtls/private.h"
+#include "private-lib-core.h"
+#include "private-lib-tls-mbedtls.h"
#include <mbedtls/rsa.h>
LWS_VISIBLE void
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
static int
OpenSSL_client_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
#include <mbedtls/x509_csr.h>
int
--- /dev/null
+/*
+ * libwebsockets - mbedTLS-specific lws apis
+ *
+ * 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
+ */
+
+#include "private-lib-core.h"
+#include "private-lib-tls-mbedtls.h"
+
+
+LWS_VISIBLE void
+lws_ssl_destroy(struct lws_vhost *vhost)
+{
+ if (!lws_check_opt(vhost->context->options,
+ LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT))
+ return;
+
+ if (vhost->tls.ssl_ctx)
+ SSL_CTX_free(vhost->tls.ssl_ctx);
+ if (!vhost->tls.user_supplied_ssl_ctx && vhost->tls.ssl_client_ctx)
+ SSL_CTX_free(vhost->tls.ssl_client_ctx);
+
+ if (vhost->tls.x509_client_CA)
+ X509_free(vhost->tls.x509_client_CA);
+}
+
+LWS_VISIBLE int
+lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len)
+{
+ struct lws_context *context = wsi->context;
+ struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
+ int n = 0, m;
+
+ if (!wsi->tls.ssl)
+ return lws_ssl_capable_read_no_ssl(wsi, buf, len);
+
+ lws_stats_bump(pt, LWSSTATS_C_API_READ, 1);
+
+ errno = 0;
+ n = SSL_read(wsi->tls.ssl, buf, len);
+#if defined(LWS_WITH_ESP32)
+ if (!n && errno == LWS_ENOTCONN) {
+ lwsl_debug("%p: SSL_read ENOTCONN\n", wsi);
+ return LWS_SSL_CAPABLE_ERROR;
+ }
+#endif
+#if defined(LWS_WITH_STATS)
+ if (!wsi->seen_rx && wsi->accept_start_us) {
+ lws_stats_bump(pt, LWSSTATS_US_SSL_RX_DELAY_AVG,
+ lws_now_usecs() - wsi->accept_start_us);
+ lws_stats_bump(pt, LWSSTATS_C_SSL_CONNS_HAD_RX, 1);
+ wsi->seen_rx = 1;
+ }
+#endif
+
+
+ lwsl_debug("%p: SSL_read says %d\n", wsi, n);
+ /* manpage: returning 0 means connection shut down */
+ if (!n) {
+ wsi->socket_is_permanently_unusable = 1;
+
+ return LWS_SSL_CAPABLE_ERROR;
+ }
+
+ if (n < 0) {
+ m = SSL_get_error(wsi->tls.ssl, n);
+ lwsl_debug("%p: ssl err %d errno %d\n", wsi, m, errno);
+ if (errno == LWS_ENOTCONN) {
+ /* If the socket isn't connected anymore, bail out. */
+ wsi->socket_is_permanently_unusable = 1;
+ return LWS_SSL_CAPABLE_ERROR;
+ }
+ if (m == SSL_ERROR_ZERO_RETURN ||
+ m == SSL_ERROR_SYSCALL)
+ return LWS_SSL_CAPABLE_ERROR;
+
+ if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) {
+ lwsl_debug("%s: WANT_READ\n", __func__);
+ lwsl_debug("%p: LWS_SSL_CAPABLE_MORE_SERVICE\n", wsi);
+ return LWS_SSL_CAPABLE_MORE_SERVICE;
+ }
+ if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) {
+ lwsl_debug("%s: WANT_WRITE\n", __func__);
+ lwsl_debug("%p: LWS_SSL_CAPABLE_MORE_SERVICE\n", wsi);
+ return LWS_SSL_CAPABLE_MORE_SERVICE;
+ }
+ wsi->socket_is_permanently_unusable = 1;
+
+ return LWS_SSL_CAPABLE_ERROR;
+ }
+
+ lws_stats_bump(pt, LWSSTATS_B_READ, n);
+
+ if (wsi->vhost)
+ wsi->vhost->conn_stats.rx += n;
+
+ /*
+ * if it was our buffer that limited what we read,
+ * check if SSL has additional data pending inside SSL buffers.
+ *
+ * Because these won't signal at the network layer with POLLIN
+ * and if we don't realize, this data will sit there forever
+ */
+ if (n != len)
+ goto bail;
+ if (!wsi->tls.ssl)
+ goto bail;
+
+ if (SSL_pending(wsi->tls.ssl) &&
+ lws_dll2_is_detached(&wsi->tls.dll_pending_tls))
+ lws_dll2_add_head(&wsi->tls.dll_pending_tls,
+ &pt->tls.dll_pending_tls_owner);
+
+ return n;
+bail:
+ lws_ssl_remove_wsi_from_buffered_list(wsi);
+
+ return n;
+}
+
+LWS_VISIBLE int
+lws_ssl_pending(struct lws *wsi)
+{
+ if (!wsi->tls.ssl)
+ return 0;
+
+ return SSL_pending(wsi->tls.ssl);
+}
+
+LWS_VISIBLE int
+lws_ssl_capable_write(struct lws *wsi, unsigned char *buf, int len)
+{
+ int n, m;
+
+ if (!wsi->tls.ssl)
+ return lws_ssl_capable_write_no_ssl(wsi, buf, len);
+
+ n = SSL_write(wsi->tls.ssl, buf, len);
+ if (n > 0)
+ return n;
+
+ m = SSL_get_error(wsi->tls.ssl, n);
+ if (m != SSL_ERROR_SYSCALL) {
+ if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) {
+ lwsl_notice("%s: want read\n", __func__);
+
+ return LWS_SSL_CAPABLE_MORE_SERVICE;
+ }
+
+ if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) {
+ lws_set_blocking_send(wsi);
+ lwsl_debug("%s: want write\n", __func__);
+
+ return LWS_SSL_CAPABLE_MORE_SERVICE;
+ }
+ }
+
+ lwsl_debug("%s failed: %d\n",__func__, m);
+ wsi->socket_is_permanently_unusable = 1;
+
+ return LWS_SSL_CAPABLE_ERROR;
+}
+
+int openssl_SSL_CTX_private_data_index;
+
+void
+lws_ssl_info_callback(const SSL *ssl, int where, int ret)
+{
+ struct lws *wsi;
+ struct lws_context *context;
+ struct lws_ssl_info si;
+
+ context = (struct lws_context *)SSL_CTX_get_ex_data(
+ SSL_get_SSL_CTX(ssl),
+ openssl_SSL_CTX_private_data_index);
+ if (!context)
+ return;
+ wsi = wsi_from_fd(context, SSL_get_fd(ssl));
+ if (!wsi)
+ return;
+
+ if (!(where & wsi->vhost->tls.ssl_info_event_mask))
+ return;
+
+ si.where = where;
+ si.ret = ret;
+
+ if (user_callback_handle_rxflow(wsi->protocol->callback,
+ wsi, LWS_CALLBACK_SSL_INFO,
+ wsi->user_space, &si, 0))
+ lws_set_timeout(wsi, PENDING_TIMEOUT_KILLED_BY_SSL_INFO, -1);
+}
+
+
+LWS_VISIBLE int
+lws_ssl_close(struct lws *wsi)
+{
+ lws_sockfd_type n;
+
+ if (!wsi->tls.ssl)
+ return 0; /* not handled */
+
+#if defined (LWS_HAVE_SSL_SET_INFO_CALLBACK)
+ /* kill ssl callbacks, becausse we will remove the fd from the
+ * table linking it to the wsi
+ */
+ if (wsi->vhost->tls.ssl_info_event_mask)
+ SSL_set_info_callback(wsi->tls.ssl, NULL);
+#endif
+
+ n = SSL_get_fd(wsi->tls.ssl);
+ if (!wsi->socket_is_permanently_unusable)
+ SSL_shutdown(wsi->tls.ssl);
+ compatible_close(n);
+ SSL_free(wsi->tls.ssl);
+ wsi->tls.ssl = NULL;
+
+ if (!lwsi_role_client(wsi) &&
+ wsi->context->simultaneous_ssl_restriction &&
+ wsi->context->simultaneous_ssl-- ==
+ wsi->context->simultaneous_ssl_restriction)
+ /* we made space and can do an accept */
+ lws_gate_accepts(wsi->context, 1);
+
+#if defined(LWS_WITH_STATS)
+ wsi->context->updated = 1;
+#endif
+
+ return 1; /* handled */
+}
+
+void
+lws_ssl_SSL_CTX_destroy(struct lws_vhost *vhost)
+{
+ if (vhost->tls.ssl_ctx)
+ SSL_CTX_free(vhost->tls.ssl_ctx);
+
+ if (!vhost->tls.user_supplied_ssl_ctx && vhost->tls.ssl_client_ctx)
+ SSL_CTX_free(vhost->tls.ssl_client_ctx);
+#if defined(LWS_WITH_ACME)
+ lws_tls_acme_sni_cert_destroy(vhost);
+#endif
+}
+
+void
+lws_ssl_context_destroy(struct lws_context *context)
+{
+}
+
+lws_tls_ctx *
+lws_tls_ctx_from_wsi(struct lws *wsi)
+{
+ if (!wsi->tls.ssl)
+ return NULL;
+
+ return SSL_get_SSL_CTX(wsi->tls.ssl);
+}
+
+enum lws_ssl_capable_status
+__lws_tls_shutdown(struct lws *wsi)
+{
+ int n = SSL_shutdown(wsi->tls.ssl);
+
+ lwsl_debug("SSL_shutdown=%d for fd %d\n", n, wsi->desc.sockfd);
+
+ switch (n) {
+ case 1: /* successful completion */
+ n = shutdown(wsi->desc.sockfd, SHUT_WR);
+ return LWS_SSL_CAPABLE_DONE;
+
+ case 0: /* needs a retry */
+ __lws_change_pollfd(wsi, 0, LWS_POLLIN);
+ return LWS_SSL_CAPABLE_MORE_SERVICE;
+
+ default: /* fatal error, or WANT */
+ n = SSL_get_error(wsi->tls.ssl, n);
+ if (n != SSL_ERROR_SYSCALL && n != SSL_ERROR_SSL) {
+ if (SSL_want_read(wsi->tls.ssl)) {
+ lwsl_debug("(wants read)\n");
+ __lws_change_pollfd(wsi, 0, LWS_POLLIN);
+ return LWS_SSL_CAPABLE_MORE_SERVICE_READ;
+ }
+ if (SSL_want_write(wsi->tls.ssl)) {
+ lwsl_debug("(wants write)\n");
+ __lws_change_pollfd(wsi, 0, LWS_POLLOUT);
+ return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE;
+ }
+ }
+ return LWS_SSL_CAPABLE_ERROR;
+ }
+}
+
+
+static int
+tops_fake_POLLIN_for_buffered_mbedtls(struct lws_context_per_thread *pt)
+{
+ return lws_tls_fake_POLLIN_for_buffered(pt);
+}
+
+const struct lws_tls_ops tls_ops_mbedtls = {
+ /* fake_POLLIN_for_buffered */ tops_fake_POLLIN_for_buffered_mbedtls,
+};
--- /dev/null
+/*
+ * libwebsockets - mbedTLS-specific lws apis
+ *
+ * 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
+ */
+
+#include "private-lib-core.h"
+#include "private-lib-tls-mbedtls.h"
+
+void
+lws_tls_err_describe_clear(void)
+{
+}
+
+int
+lws_context_init_ssl_library(const struct lws_context_creation_info *info)
+{
+ lwsl_info(" Compiled with MbedTLS support\n");
+
+ if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT))
+ lwsl_info(" SSL disabled: no "
+ "LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT\n");
+
+ return 0;
+}
+
+void
+lws_context_deinit_ssl_library(struct lws_context *context)
+{
+
+}
--- /dev/null
+/*
+ * libwebsockets - mbedTLS-specific lws apis
+ *
+ * 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
+ */
+
+#include "private-lib-core.h"
+#include "private-lib-tls-mbedtls.h"
+#include <mbedtls/oid.h>
+
+#if defined(LWS_PLAT_OPTEE) || defined(OPTEE_DEV_KIT)
+struct tm {
+int tm_sec; // seconds [0,61]
+int tm_min; // minutes [0,59]
+int tm_hour; // hour [0,23]
+int tm_mday; // day of month [1,31]
+int tm_mon; // month of year [0,11]
+int tm_year; // years since 1900
+int tm_wday; // day of week [0,6] (Sunday = 0)
+int tm_yday; // day of year [0,365]
+int tm_isdst; // daylight savings flag
+};
+time_t mktime(struct tm *t)
+{
+ return (time_t)0;
+}
+#endif
+
+static time_t
+lws_tls_mbedtls_time_to_unix(mbedtls_x509_time *xtime)
+{
+ struct tm t;
+
+ if (!xtime || !xtime->year || xtime->year < 0)
+ return (time_t)(long long)-1;
+
+ memset(&t, 0, sizeof(t));
+
+ t.tm_year = xtime->year - 1900;
+ t.tm_mon = xtime->mon - 1; /* mbedtls months are 1+, tm are 0+ */
+ t.tm_mday = xtime->day - 1; /* mbedtls days are 1+, tm are 0+ */
+ t.tm_hour = xtime->hour;
+ t.tm_min = xtime->min;
+ t.tm_sec = xtime->sec;
+ t.tm_isdst = -1;
+
+ return mktime(&t);
+}
+
+static int
+lws_tls_mbedtls_get_x509_name(mbedtls_x509_name *name,
+ union lws_tls_cert_info_results *buf, size_t len)
+{
+ while (name) {
+ if (MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid)) {
+ name = name->next;
+ continue;
+ }
+
+ if (len - 1 < name->val.len)
+ return -1;
+
+ memcpy(&buf->ns.name[0], name->val.p, name->val.len);
+ buf->ns.name[name->val.len] = '\0';
+ buf->ns.len = name->val.len;
+
+ return 0;
+ }
+
+ return -1;
+}
+
+static int
+lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type,
+ union lws_tls_cert_info_results *buf, size_t len)
+{
+ if (!x509)
+ return -1;
+
+ switch (type) {
+ case LWS_TLS_CERT_INFO_VALIDITY_FROM:
+ buf->time = lws_tls_mbedtls_time_to_unix(&x509->valid_from);
+ if (buf->time == (time_t)(long long)-1)
+ return -1;
+ break;
+
+ case LWS_TLS_CERT_INFO_VALIDITY_TO:
+ buf->time = lws_tls_mbedtls_time_to_unix(&x509->valid_to);
+ if (buf->time == (time_t)(long long)-1)
+ return -1;
+ break;
+
+ case LWS_TLS_CERT_INFO_COMMON_NAME:
+ return lws_tls_mbedtls_get_x509_name(&x509->subject, buf, len);
+
+ case LWS_TLS_CERT_INFO_ISSUER_NAME:
+ return lws_tls_mbedtls_get_x509_name(&x509->issuer, buf, len);
+
+ case LWS_TLS_CERT_INFO_USAGE:
+ buf->usage = x509->key_usage;
+ break;
+
+ case LWS_TLS_CERT_INFO_OPAQUE_PUBLIC_KEY:
+ {
+ char *p = buf->ns.name;
+ size_t r = len, u;
+
+ switch (mbedtls_pk_get_type(&x509->pk)) {
+ case MBEDTLS_PK_RSA:
+ {
+ mbedtls_rsa_context *rsa = mbedtls_pk_rsa(x509->pk);
+
+ if (mbedtls_mpi_write_string(&rsa->N, 16, p, r, &u))
+ return -1;
+ r -= u;
+ p += u;
+ if (mbedtls_mpi_write_string(&rsa->E, 16, p, r, &u))
+ return -1;
+
+ p += u;
+ buf->ns.len = lws_ptr_diff(p, buf->ns.name);
+ break;
+ }
+ case MBEDTLS_PK_ECKEY:
+ {
+ mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(x509->pk);
+
+ if (mbedtls_mpi_write_string(&ecp->Q.X, 16, p, r, &u))
+ return -1;
+ r -= u;
+ p += u;
+ if (mbedtls_mpi_write_string(&ecp->Q.Y, 16, p, r, &u))
+ return -1;
+ r -= u;
+ p += u;
+ if (mbedtls_mpi_write_string(&ecp->Q.Z, 16, p, r, &u))
+ return -1;
+ p += u;
+ buf->ns.len = lws_ptr_diff(p, buf->ns.name);
+ break;
+ }
+ default:
+ lwsl_notice("%s: x509 has unsupported pubkey type %d\n",
+ __func__,
+ mbedtls_pk_get_type(&x509->pk));
+
+ return -1;
+ }
+ break;
+ }
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+#if defined(LWS_WITH_NETWORK)
+int
+lws_tls_vhost_cert_info(struct lws_vhost *vhost, enum lws_tls_cert_info type,
+ union lws_tls_cert_info_results *buf, size_t len)
+{
+ mbedtls_x509_crt *x509;
+
+ x509 = ssl_ctx_get_mbedtls_x509_crt(vhost->tls.ssl_ctx);
+
+ return lws_tls_mbedtls_cert_info(x509, type, buf, len);
+}
+
+int
+lws_tls_peer_cert_info(struct lws *wsi, enum lws_tls_cert_info type,
+ union lws_tls_cert_info_results *buf, size_t len)
+{
+ mbedtls_x509_crt *x509;
+
+ wsi = lws_get_network_wsi(wsi);
+
+ x509 = ssl_get_peer_mbedtls_x509_crt(wsi->tls.ssl);
+
+ if (!x509)
+ return -1;
+
+ switch (type) {
+ case LWS_TLS_CERT_INFO_VERIFIED:
+ buf->verified = SSL_get_verify_result(wsi->tls.ssl) == X509_V_OK;
+ return 0;
+ default:
+ return lws_tls_mbedtls_cert_info(x509, type, buf, len);
+ }
+
+ return -1;
+}
+#endif
+
+int
+lws_x509_info(struct lws_x509_cert *x509, enum lws_tls_cert_info type,
+ union lws_tls_cert_info_results *buf, size_t len)
+{
+ return lws_tls_mbedtls_cert_info(&x509->cert, type, buf, len);
+}
+
+int
+lws_x509_create(struct lws_x509_cert **x509)
+{
+ *x509 = lws_malloc(sizeof(**x509), __func__);
+
+ return !(*x509);
+}
+
+/*
+ * Parse one DER-encoded or one or more concatenated PEM-encoded certificates
+ * and add them to the chained list.
+ */
+
+int
+lws_x509_parse_from_pem(struct lws_x509_cert *x509, const void *pem, size_t len)
+{
+ int ret;
+
+ mbedtls_x509_crt_init(&x509->cert);
+
+ ret = mbedtls_x509_crt_parse(&x509->cert, pem, len);
+ if (ret) {
+ mbedtls_x509_crt_free(&x509->cert);
+ lwsl_err("%s: unable to parse PEM cert: -0x%x\n",
+ __func__, -ret);
+
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+lws_x509_verify(struct lws_x509_cert *x509, struct lws_x509_cert *trusted,
+ const char *common_name)
+{
+ uint32_t flags = 0;
+ int ret;
+
+ ret = mbedtls_x509_crt_verify_with_profile(&x509->cert, &trusted->cert,
+ NULL,
+ &mbedtls_x509_crt_profile_next,
+ common_name, &flags, NULL,
+ NULL);
+
+ if (ret) {
+ lwsl_err("%s: unable to parse PEM cert: -0x%x\n",
+ __func__, -ret);
+
+ return -1;
+ }
+
+ return 0;
+}
+
+#if defined(LWS_WITH_JOSE)
+
+int
+lws_x509_public_to_jwk(struct lws_jwk *jwk, struct lws_x509_cert *x509,
+ const char *curves, int rsa_min_bits)
+{
+ int kt = mbedtls_pk_get_type(&x509->cert.pk), n, count = 0, ret = -1;
+ mbedtls_rsa_context *rsactx;
+ mbedtls_ecp_keypair *ecpctx;
+ mbedtls_mpi *mpi[LWS_GENCRYPTO_RSA_KEYEL_COUNT];
+
+ memset(jwk, 0, sizeof(*jwk));
+
+ switch (kt) {
+ case MBEDTLS_PK_RSA:
+ lwsl_notice("%s: RSA key\n", __func__);
+ jwk->kty = LWS_GENCRYPTO_KTY_RSA;
+ rsactx = mbedtls_pk_rsa(x509->cert.pk);
+
+ mpi[LWS_GENCRYPTO_RSA_KEYEL_E] = &rsactx->E;
+ mpi[LWS_GENCRYPTO_RSA_KEYEL_N] = &rsactx->N;
+ mpi[LWS_GENCRYPTO_RSA_KEYEL_D] = &rsactx->D;
+ mpi[LWS_GENCRYPTO_RSA_KEYEL_P] = &rsactx->P;
+ mpi[LWS_GENCRYPTO_RSA_KEYEL_Q] = &rsactx->Q;
+ mpi[LWS_GENCRYPTO_RSA_KEYEL_DP] = &rsactx->DP;
+ mpi[LWS_GENCRYPTO_RSA_KEYEL_DQ] = &rsactx->DQ;
+ mpi[LWS_GENCRYPTO_RSA_KEYEL_QI] = &rsactx->QP;
+
+ count = LWS_GENCRYPTO_RSA_KEYEL_COUNT;
+ n = LWS_GENCRYPTO_RSA_KEYEL_E;
+ break;
+
+ case MBEDTLS_PK_ECKEY:
+ lwsl_notice("%s: EC key\n", __func__);
+ jwk->kty = LWS_GENCRYPTO_KTY_EC;
+ ecpctx = mbedtls_pk_ec(x509->cert.pk);
+ mpi[LWS_GENCRYPTO_EC_KEYEL_X] = &ecpctx->Q.X;
+ mpi[LWS_GENCRYPTO_EC_KEYEL_D] = &ecpctx->d;
+ mpi[LWS_GENCRYPTO_EC_KEYEL_Y] = &ecpctx->Q.Y;
+
+ if (lws_genec_confirm_curve_allowed_by_tls_id(curves,
+ ecpctx->grp.id, jwk))
+ /* already logged */
+ goto bail;
+
+ count = LWS_GENCRYPTO_EC_KEYEL_COUNT;
+ n = LWS_GENCRYPTO_EC_KEYEL_X;
+ break;
+ default:
+ lwsl_err("%s: key type %d not supported\n", __func__, kt);
+
+ return -1;
+ }
+
+ for (; n < count; n++) {
+ if (!mbedtls_mpi_size(mpi[n]))
+ continue;
+
+ jwk->e[n].buf = lws_malloc(mbedtls_mpi_size(mpi[n]), "certjwk");
+ if (!jwk->e[n].buf)
+ goto bail;
+ jwk->e[n].len = mbedtls_mpi_size(mpi[n]);
+ mbedtls_mpi_write_binary(mpi[n], jwk->e[n].buf, jwk->e[n].len);
+ }
+
+ ret = 0;
+
+bail:
+ /* jwk destroy will clean up partials */
+ if (ret)
+ lws_jwk_destroy(jwk);
+
+ return ret;
+}
+
+int
+lws_x509_jwk_privkey_pem(struct lws_jwk *jwk, void *pem, size_t len,
+ const char *passphrase)
+{
+ mbedtls_rsa_context *rsactx;
+ mbedtls_ecp_keypair *ecpctx;
+ mbedtls_pk_context pk;
+ mbedtls_mpi *mpi[LWS_GENCRYPTO_RSA_KEYEL_COUNT];
+ int n, ret = -1, count = 0;
+
+ mbedtls_pk_init(&pk);
+
+ n = 0;
+ if (passphrase)
+ n = strlen(passphrase);
+ n = mbedtls_pk_parse_key(&pk, pem, len, (uint8_t *)passphrase, n);
+ if (n) {
+ lwsl_err("%s: parse PEM key failed: -0x%x\n", __func__, -n);
+
+ return -1;
+ }
+
+ /* the incoming private key type */
+ switch (mbedtls_pk_get_type(&pk)) {
+ case MBEDTLS_PK_RSA:
+ if (jwk->kty != LWS_GENCRYPTO_KTY_RSA) {
+ lwsl_err("%s: RSA privkey, non-RSA jwk\n", __func__);
+ goto bail;
+ }
+ rsactx = mbedtls_pk_rsa(pk);
+ mpi[LWS_GENCRYPTO_RSA_KEYEL_D] = &rsactx->D;
+ mpi[LWS_GENCRYPTO_RSA_KEYEL_P] = &rsactx->P;
+ mpi[LWS_GENCRYPTO_RSA_KEYEL_Q] = &rsactx->Q;
+ n = LWS_GENCRYPTO_RSA_KEYEL_D;
+ count = LWS_GENCRYPTO_RSA_KEYEL_Q + 1;
+ break;
+ case MBEDTLS_PK_ECKEY:
+ if (jwk->kty != LWS_GENCRYPTO_KTY_EC) {
+ lwsl_err("%s: EC privkey, non-EC jwk\n", __func__);
+ goto bail;
+ }
+ ecpctx = mbedtls_pk_ec(pk);
+ mpi[LWS_GENCRYPTO_EC_KEYEL_D] = &ecpctx->d;
+ n = LWS_GENCRYPTO_EC_KEYEL_D;
+ count = n + 1;
+ break;
+ default:
+ lwsl_err("%s: unusable key type %d\n", __func__,
+ mbedtls_pk_get_type(&pk));
+ goto bail;
+ }
+
+ for (; n < count; n++) {
+ if (!mbedtls_mpi_size(mpi[n])) {
+ lwsl_err("%s: empty privkey\n", __func__);
+ goto bail;
+ }
+
+ jwk->e[n].buf = lws_malloc(mbedtls_mpi_size(mpi[n]), "certjwk");
+ if (!jwk->e[n].buf)
+ goto bail;
+ jwk->e[n].len = mbedtls_mpi_size(mpi[n]);
+ mbedtls_mpi_write_binary(mpi[n], jwk->e[n].buf, jwk->e[n].len);
+ }
+
+ ret = 0;
+
+bail:
+ mbedtls_pk_free(&pk);
+
+ return ret;
+}
+#endif
+
+void
+lws_x509_destroy(struct lws_x509_cert **x509)
+{
+ if (!*x509)
+ return;
+
+ mbedtls_x509_crt_free(&(*x509)->cert);
+
+ lws_free_set_NULL(*x509);
+}
--- /dev/null
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010 - 2018 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
+ *
+ * gencrypto mbedtls-specific helper declarations
+ */
+
+#include <mbedtls/x509_crl.h>
+
+struct lws_x509_cert {
+ mbedtls_x509_crt cert; /* has a .next for linked-list / chain */
+};
+
+mbedtls_md_type_t
+lws_gencrypto_mbedtls_hash_to_MD_TYPE(enum lws_genhash_types hash_type);
+
+int
+lws_gencrypto_mbedtls_rngf(void *context, unsigned char *buf, size_t len);
+++ /dev/null
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 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
- *
- * gencrypto mbedtls-specific helper declarations
- */
-
-#include <mbedtls/x509_crl.h>
-
-struct lws_x509_cert {
- mbedtls_x509_crt cert; /* has a .next for linked-list / chain */
-};
-
-mbedtls_md_type_t
-lws_gencrypto_mbedtls_hash_to_MD_TYPE(enum lws_genhash_types hash_type);
-
-int
-lws_gencrypto_mbedtls_rngf(void *context, unsigned char *buf, size_t len);
+++ /dev/null
-/*
- * libwebsockets - mbedTLS-specific lws apis
- *
- * 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
- */
-
-#include "core/private.h"
-#include "tls/mbedtls/private.h"
-
-
-LWS_VISIBLE void
-lws_ssl_destroy(struct lws_vhost *vhost)
-{
- if (!lws_check_opt(vhost->context->options,
- LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT))
- return;
-
- if (vhost->tls.ssl_ctx)
- SSL_CTX_free(vhost->tls.ssl_ctx);
- if (!vhost->tls.user_supplied_ssl_ctx && vhost->tls.ssl_client_ctx)
- SSL_CTX_free(vhost->tls.ssl_client_ctx);
-
- if (vhost->tls.x509_client_CA)
- X509_free(vhost->tls.x509_client_CA);
-}
-
-LWS_VISIBLE int
-lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len)
-{
- struct lws_context *context = wsi->context;
- struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
- int n = 0, m;
-
- if (!wsi->tls.ssl)
- return lws_ssl_capable_read_no_ssl(wsi, buf, len);
-
- lws_stats_bump(pt, LWSSTATS_C_API_READ, 1);
-
- errno = 0;
- n = SSL_read(wsi->tls.ssl, buf, len);
-#if defined(LWS_WITH_ESP32)
- if (!n && errno == LWS_ENOTCONN) {
- lwsl_debug("%p: SSL_read ENOTCONN\n", wsi);
- return LWS_SSL_CAPABLE_ERROR;
- }
-#endif
-#if defined(LWS_WITH_STATS)
- if (!wsi->seen_rx && wsi->accept_start_us) {
- lws_stats_bump(pt, LWSSTATS_US_SSL_RX_DELAY_AVG,
- lws_now_usecs() - wsi->accept_start_us);
- lws_stats_bump(pt, LWSSTATS_C_SSL_CONNS_HAD_RX, 1);
- wsi->seen_rx = 1;
- }
-#endif
-
-
- lwsl_debug("%p: SSL_read says %d\n", wsi, n);
- /* manpage: returning 0 means connection shut down */
- if (!n) {
- wsi->socket_is_permanently_unusable = 1;
-
- return LWS_SSL_CAPABLE_ERROR;
- }
-
- if (n < 0) {
- m = SSL_get_error(wsi->tls.ssl, n);
- lwsl_debug("%p: ssl err %d errno %d\n", wsi, m, errno);
- if (errno == LWS_ENOTCONN) {
- /* If the socket isn't connected anymore, bail out. */
- wsi->socket_is_permanently_unusable = 1;
- return LWS_SSL_CAPABLE_ERROR;
- }
- if (m == SSL_ERROR_ZERO_RETURN ||
- m == SSL_ERROR_SYSCALL)
- return LWS_SSL_CAPABLE_ERROR;
-
- if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) {
- lwsl_debug("%s: WANT_READ\n", __func__);
- lwsl_debug("%p: LWS_SSL_CAPABLE_MORE_SERVICE\n", wsi);
- return LWS_SSL_CAPABLE_MORE_SERVICE;
- }
- if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) {
- lwsl_debug("%s: WANT_WRITE\n", __func__);
- lwsl_debug("%p: LWS_SSL_CAPABLE_MORE_SERVICE\n", wsi);
- return LWS_SSL_CAPABLE_MORE_SERVICE;
- }
- wsi->socket_is_permanently_unusable = 1;
-
- return LWS_SSL_CAPABLE_ERROR;
- }
-
- lws_stats_bump(pt, LWSSTATS_B_READ, n);
-
- if (wsi->vhost)
- wsi->vhost->conn_stats.rx += n;
-
- /*
- * if it was our buffer that limited what we read,
- * check if SSL has additional data pending inside SSL buffers.
- *
- * Because these won't signal at the network layer with POLLIN
- * and if we don't realize, this data will sit there forever
- */
- if (n != len)
- goto bail;
- if (!wsi->tls.ssl)
- goto bail;
-
- if (SSL_pending(wsi->tls.ssl) &&
- lws_dll2_is_detached(&wsi->tls.dll_pending_tls))
- lws_dll2_add_head(&wsi->tls.dll_pending_tls,
- &pt->tls.dll_pending_tls_owner);
-
- return n;
-bail:
- lws_ssl_remove_wsi_from_buffered_list(wsi);
-
- return n;
-}
-
-LWS_VISIBLE int
-lws_ssl_pending(struct lws *wsi)
-{
- if (!wsi->tls.ssl)
- return 0;
-
- return SSL_pending(wsi->tls.ssl);
-}
-
-LWS_VISIBLE int
-lws_ssl_capable_write(struct lws *wsi, unsigned char *buf, int len)
-{
- int n, m;
-
- if (!wsi->tls.ssl)
- return lws_ssl_capable_write_no_ssl(wsi, buf, len);
-
- n = SSL_write(wsi->tls.ssl, buf, len);
- if (n > 0)
- return n;
-
- m = SSL_get_error(wsi->tls.ssl, n);
- if (m != SSL_ERROR_SYSCALL) {
- if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) {
- lwsl_notice("%s: want read\n", __func__);
-
- return LWS_SSL_CAPABLE_MORE_SERVICE;
- }
-
- if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) {
- lws_set_blocking_send(wsi);
- lwsl_debug("%s: want write\n", __func__);
-
- return LWS_SSL_CAPABLE_MORE_SERVICE;
- }
- }
-
- lwsl_debug("%s failed: %d\n",__func__, m);
- wsi->socket_is_permanently_unusable = 1;
-
- return LWS_SSL_CAPABLE_ERROR;
-}
-
-int openssl_SSL_CTX_private_data_index;
-
-void
-lws_ssl_info_callback(const SSL *ssl, int where, int ret)
-{
- struct lws *wsi;
- struct lws_context *context;
- struct lws_ssl_info si;
-
- context = (struct lws_context *)SSL_CTX_get_ex_data(
- SSL_get_SSL_CTX(ssl),
- openssl_SSL_CTX_private_data_index);
- if (!context)
- return;
- wsi = wsi_from_fd(context, SSL_get_fd(ssl));
- if (!wsi)
- return;
-
- if (!(where & wsi->vhost->tls.ssl_info_event_mask))
- return;
-
- si.where = where;
- si.ret = ret;
-
- if (user_callback_handle_rxflow(wsi->protocol->callback,
- wsi, LWS_CALLBACK_SSL_INFO,
- wsi->user_space, &si, 0))
- lws_set_timeout(wsi, PENDING_TIMEOUT_KILLED_BY_SSL_INFO, -1);
-}
-
-
-LWS_VISIBLE int
-lws_ssl_close(struct lws *wsi)
-{
- lws_sockfd_type n;
-
- if (!wsi->tls.ssl)
- return 0; /* not handled */
-
-#if defined (LWS_HAVE_SSL_SET_INFO_CALLBACK)
- /* kill ssl callbacks, becausse we will remove the fd from the
- * table linking it to the wsi
- */
- if (wsi->vhost->tls.ssl_info_event_mask)
- SSL_set_info_callback(wsi->tls.ssl, NULL);
-#endif
-
- n = SSL_get_fd(wsi->tls.ssl);
- if (!wsi->socket_is_permanently_unusable)
- SSL_shutdown(wsi->tls.ssl);
- compatible_close(n);
- SSL_free(wsi->tls.ssl);
- wsi->tls.ssl = NULL;
-
- if (!lwsi_role_client(wsi) &&
- wsi->context->simultaneous_ssl_restriction &&
- wsi->context->simultaneous_ssl-- ==
- wsi->context->simultaneous_ssl_restriction)
- /* we made space and can do an accept */
- lws_gate_accepts(wsi->context, 1);
-
-#if defined(LWS_WITH_STATS)
- wsi->context->updated = 1;
-#endif
-
- return 1; /* handled */
-}
-
-void
-lws_ssl_SSL_CTX_destroy(struct lws_vhost *vhost)
-{
- if (vhost->tls.ssl_ctx)
- SSL_CTX_free(vhost->tls.ssl_ctx);
-
- if (!vhost->tls.user_supplied_ssl_ctx && vhost->tls.ssl_client_ctx)
- SSL_CTX_free(vhost->tls.ssl_client_ctx);
-#if defined(LWS_WITH_ACME)
- lws_tls_acme_sni_cert_destroy(vhost);
-#endif
-}
-
-void
-lws_ssl_context_destroy(struct lws_context *context)
-{
-}
-
-lws_tls_ctx *
-lws_tls_ctx_from_wsi(struct lws *wsi)
-{
- if (!wsi->tls.ssl)
- return NULL;
-
- return SSL_get_SSL_CTX(wsi->tls.ssl);
-}
-
-enum lws_ssl_capable_status
-__lws_tls_shutdown(struct lws *wsi)
-{
- int n = SSL_shutdown(wsi->tls.ssl);
-
- lwsl_debug("SSL_shutdown=%d for fd %d\n", n, wsi->desc.sockfd);
-
- switch (n) {
- case 1: /* successful completion */
- n = shutdown(wsi->desc.sockfd, SHUT_WR);
- return LWS_SSL_CAPABLE_DONE;
-
- case 0: /* needs a retry */
- __lws_change_pollfd(wsi, 0, LWS_POLLIN);
- return LWS_SSL_CAPABLE_MORE_SERVICE;
-
- default: /* fatal error, or WANT */
- n = SSL_get_error(wsi->tls.ssl, n);
- if (n != SSL_ERROR_SYSCALL && n != SSL_ERROR_SSL) {
- if (SSL_want_read(wsi->tls.ssl)) {
- lwsl_debug("(wants read)\n");
- __lws_change_pollfd(wsi, 0, LWS_POLLIN);
- return LWS_SSL_CAPABLE_MORE_SERVICE_READ;
- }
- if (SSL_want_write(wsi->tls.ssl)) {
- lwsl_debug("(wants write)\n");
- __lws_change_pollfd(wsi, 0, LWS_POLLOUT);
- return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE;
- }
- }
- return LWS_SSL_CAPABLE_ERROR;
- }
-}
-
-
-static int
-tops_fake_POLLIN_for_buffered_mbedtls(struct lws_context_per_thread *pt)
-{
- return lws_tls_fake_POLLIN_for_buffered(pt);
-}
-
-const struct lws_tls_ops tls_ops_mbedtls = {
- /* fake_POLLIN_for_buffered */ tops_fake_POLLIN_for_buffered_mbedtls,
-};
+++ /dev/null
-/*
- * libwebsockets - mbedTLS-specific lws apis
- *
- * 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
- */
-
-#include "core/private.h"
-#include "tls/mbedtls/private.h"
-
-void
-lws_tls_err_describe_clear(void)
-{
-}
-
-int
-lws_context_init_ssl_library(const struct lws_context_creation_info *info)
-{
- lwsl_info(" Compiled with MbedTLS support\n");
-
- if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT))
- lwsl_info(" SSL disabled: no "
- "LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT\n");
-
- return 0;
-}
-
-void
-lws_context_deinit_ssl_library(struct lws_context *context)
-{
-
-}
#ifndef _SSL_DEBUG_H_
#define _SSL_DEBUG_H_
-#include "platform/ssl_port.h"
+#include "ssl_port.h"
#ifdef __cplusplus
extern "C" {
extern "C" {
#endif
-//#include "core/private.h"
+//#include "private-lib-core.h"
#include <lws_config.h>
#if defined(LWS_WITH_ESP32)
/* AMAZON RTOS has its own setting via MTK_MBEDTLS_CONFIG_FILE */
#endif\r
\r
#include <stdlib.h>\r
-#include "internal/ssl_x509.h"\r
-#include "internal/ssl_pkey.h"\r
+#include "ssl_x509.h"\r
+#include "ssl_pkey.h"\r
\r
/*\r
{\r
#include "ssl_dbg.h"
#include "ssl_port.h"
-#include "core/private.h"
+#include "private-lib-core.h"
char *
lws_strncpy(char *dest, const char *src, size_t size);
#include "mbedtls/error.h"
#include "mbedtls/certs.h"
-#include "core/private.h"
+#include "private-lib-core.h"
#define X509_INFO_STRING_LENGTH 8192
+++ /dev/null
-/*
- * libwebsockets - mbedTLS-specific lws apis
- *
- * 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
- */
-
-#include "core/private.h"
-#include "tls/mbedtls/private.h"
-#include <mbedtls/oid.h>
-
-#if defined(LWS_PLAT_OPTEE) || defined(OPTEE_DEV_KIT)
-struct tm {
-int tm_sec; // seconds [0,61]
-int tm_min; // minutes [0,59]
-int tm_hour; // hour [0,23]
-int tm_mday; // day of month [1,31]
-int tm_mon; // month of year [0,11]
-int tm_year; // years since 1900
-int tm_wday; // day of week [0,6] (Sunday = 0)
-int tm_yday; // day of year [0,365]
-int tm_isdst; // daylight savings flag
-};
-time_t mktime(struct tm *t)
-{
- return (time_t)0;
-}
-#endif
-
-static time_t
-lws_tls_mbedtls_time_to_unix(mbedtls_x509_time *xtime)
-{
- struct tm t;
-
- if (!xtime || !xtime->year || xtime->year < 0)
- return (time_t)(long long)-1;
-
- memset(&t, 0, sizeof(t));
-
- t.tm_year = xtime->year - 1900;
- t.tm_mon = xtime->mon - 1; /* mbedtls months are 1+, tm are 0+ */
- t.tm_mday = xtime->day - 1; /* mbedtls days are 1+, tm are 0+ */
- t.tm_hour = xtime->hour;
- t.tm_min = xtime->min;
- t.tm_sec = xtime->sec;
- t.tm_isdst = -1;
-
- return mktime(&t);
-}
-
-static int
-lws_tls_mbedtls_get_x509_name(mbedtls_x509_name *name,
- union lws_tls_cert_info_results *buf, size_t len)
-{
- while (name) {
- if (MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid)) {
- name = name->next;
- continue;
- }
-
- if (len - 1 < name->val.len)
- return -1;
-
- memcpy(&buf->ns.name[0], name->val.p, name->val.len);
- buf->ns.name[name->val.len] = '\0';
- buf->ns.len = name->val.len;
-
- return 0;
- }
-
- return -1;
-}
-
-static int
-lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type,
- union lws_tls_cert_info_results *buf, size_t len)
-{
- if (!x509)
- return -1;
-
- switch (type) {
- case LWS_TLS_CERT_INFO_VALIDITY_FROM:
- buf->time = lws_tls_mbedtls_time_to_unix(&x509->valid_from);
- if (buf->time == (time_t)(long long)-1)
- return -1;
- break;
-
- case LWS_TLS_CERT_INFO_VALIDITY_TO:
- buf->time = lws_tls_mbedtls_time_to_unix(&x509->valid_to);
- if (buf->time == (time_t)(long long)-1)
- return -1;
- break;
-
- case LWS_TLS_CERT_INFO_COMMON_NAME:
- return lws_tls_mbedtls_get_x509_name(&x509->subject, buf, len);
-
- case LWS_TLS_CERT_INFO_ISSUER_NAME:
- return lws_tls_mbedtls_get_x509_name(&x509->issuer, buf, len);
-
- case LWS_TLS_CERT_INFO_USAGE:
- buf->usage = x509->key_usage;
- break;
-
- case LWS_TLS_CERT_INFO_OPAQUE_PUBLIC_KEY:
- {
- char *p = buf->ns.name;
- size_t r = len, u;
-
- switch (mbedtls_pk_get_type(&x509->pk)) {
- case MBEDTLS_PK_RSA:
- {
- mbedtls_rsa_context *rsa = mbedtls_pk_rsa(x509->pk);
-
- if (mbedtls_mpi_write_string(&rsa->N, 16, p, r, &u))
- return -1;
- r -= u;
- p += u;
- if (mbedtls_mpi_write_string(&rsa->E, 16, p, r, &u))
- return -1;
-
- p += u;
- buf->ns.len = lws_ptr_diff(p, buf->ns.name);
- break;
- }
- case MBEDTLS_PK_ECKEY:
- {
- mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(x509->pk);
-
- if (mbedtls_mpi_write_string(&ecp->Q.X, 16, p, r, &u))
- return -1;
- r -= u;
- p += u;
- if (mbedtls_mpi_write_string(&ecp->Q.Y, 16, p, r, &u))
- return -1;
- r -= u;
- p += u;
- if (mbedtls_mpi_write_string(&ecp->Q.Z, 16, p, r, &u))
- return -1;
- p += u;
- buf->ns.len = lws_ptr_diff(p, buf->ns.name);
- break;
- }
- default:
- lwsl_notice("%s: x509 has unsupported pubkey type %d\n",
- __func__,
- mbedtls_pk_get_type(&x509->pk));
-
- return -1;
- }
- break;
- }
-
- default:
- return -1;
- }
-
- return 0;
-}
-
-#if defined(LWS_WITH_NETWORK)
-int
-lws_tls_vhost_cert_info(struct lws_vhost *vhost, enum lws_tls_cert_info type,
- union lws_tls_cert_info_results *buf, size_t len)
-{
- mbedtls_x509_crt *x509;
-
- x509 = ssl_ctx_get_mbedtls_x509_crt(vhost->tls.ssl_ctx);
-
- return lws_tls_mbedtls_cert_info(x509, type, buf, len);
-}
-
-int
-lws_tls_peer_cert_info(struct lws *wsi, enum lws_tls_cert_info type,
- union lws_tls_cert_info_results *buf, size_t len)
-{
- mbedtls_x509_crt *x509;
-
- wsi = lws_get_network_wsi(wsi);
-
- x509 = ssl_get_peer_mbedtls_x509_crt(wsi->tls.ssl);
-
- if (!x509)
- return -1;
-
- switch (type) {
- case LWS_TLS_CERT_INFO_VERIFIED:
- buf->verified = SSL_get_verify_result(wsi->tls.ssl) == X509_V_OK;
- return 0;
- default:
- return lws_tls_mbedtls_cert_info(x509, type, buf, len);
- }
-
- return -1;
-}
-#endif
-
-int
-lws_x509_info(struct lws_x509_cert *x509, enum lws_tls_cert_info type,
- union lws_tls_cert_info_results *buf, size_t len)
-{
- return lws_tls_mbedtls_cert_info(&x509->cert, type, buf, len);
-}
-
-int
-lws_x509_create(struct lws_x509_cert **x509)
-{
- *x509 = lws_malloc(sizeof(**x509), __func__);
-
- return !(*x509);
-}
-
-/*
- * Parse one DER-encoded or one or more concatenated PEM-encoded certificates
- * and add them to the chained list.
- */
-
-int
-lws_x509_parse_from_pem(struct lws_x509_cert *x509, const void *pem, size_t len)
-{
- int ret;
-
- mbedtls_x509_crt_init(&x509->cert);
-
- ret = mbedtls_x509_crt_parse(&x509->cert, pem, len);
- if (ret) {
- mbedtls_x509_crt_free(&x509->cert);
- lwsl_err("%s: unable to parse PEM cert: -0x%x\n",
- __func__, -ret);
-
- return -1;
- }
-
- return 0;
-}
-
-int
-lws_x509_verify(struct lws_x509_cert *x509, struct lws_x509_cert *trusted,
- const char *common_name)
-{
- uint32_t flags = 0;
- int ret;
-
- ret = mbedtls_x509_crt_verify_with_profile(&x509->cert, &trusted->cert,
- NULL,
- &mbedtls_x509_crt_profile_next,
- common_name, &flags, NULL,
- NULL);
-
- if (ret) {
- lwsl_err("%s: unable to parse PEM cert: -0x%x\n",
- __func__, -ret);
-
- return -1;
- }
-
- return 0;
-}
-
-#if defined(LWS_WITH_JOSE)
-
-int
-lws_x509_public_to_jwk(struct lws_jwk *jwk, struct lws_x509_cert *x509,
- const char *curves, int rsa_min_bits)
-{
- int kt = mbedtls_pk_get_type(&x509->cert.pk), n, count = 0, ret = -1;
- mbedtls_rsa_context *rsactx;
- mbedtls_ecp_keypair *ecpctx;
- mbedtls_mpi *mpi[LWS_GENCRYPTO_RSA_KEYEL_COUNT];
-
- memset(jwk, 0, sizeof(*jwk));
-
- switch (kt) {
- case MBEDTLS_PK_RSA:
- lwsl_notice("%s: RSA key\n", __func__);
- jwk->kty = LWS_GENCRYPTO_KTY_RSA;
- rsactx = mbedtls_pk_rsa(x509->cert.pk);
-
- mpi[LWS_GENCRYPTO_RSA_KEYEL_E] = &rsactx->E;
- mpi[LWS_GENCRYPTO_RSA_KEYEL_N] = &rsactx->N;
- mpi[LWS_GENCRYPTO_RSA_KEYEL_D] = &rsactx->D;
- mpi[LWS_GENCRYPTO_RSA_KEYEL_P] = &rsactx->P;
- mpi[LWS_GENCRYPTO_RSA_KEYEL_Q] = &rsactx->Q;
- mpi[LWS_GENCRYPTO_RSA_KEYEL_DP] = &rsactx->DP;
- mpi[LWS_GENCRYPTO_RSA_KEYEL_DQ] = &rsactx->DQ;
- mpi[LWS_GENCRYPTO_RSA_KEYEL_QI] = &rsactx->QP;
-
- count = LWS_GENCRYPTO_RSA_KEYEL_COUNT;
- n = LWS_GENCRYPTO_RSA_KEYEL_E;
- break;
-
- case MBEDTLS_PK_ECKEY:
- lwsl_notice("%s: EC key\n", __func__);
- jwk->kty = LWS_GENCRYPTO_KTY_EC;
- ecpctx = mbedtls_pk_ec(x509->cert.pk);
- mpi[LWS_GENCRYPTO_EC_KEYEL_X] = &ecpctx->Q.X;
- mpi[LWS_GENCRYPTO_EC_KEYEL_D] = &ecpctx->d;
- mpi[LWS_GENCRYPTO_EC_KEYEL_Y] = &ecpctx->Q.Y;
-
- if (lws_genec_confirm_curve_allowed_by_tls_id(curves,
- ecpctx->grp.id, jwk))
- /* already logged */
- goto bail;
-
- count = LWS_GENCRYPTO_EC_KEYEL_COUNT;
- n = LWS_GENCRYPTO_EC_KEYEL_X;
- break;
- default:
- lwsl_err("%s: key type %d not supported\n", __func__, kt);
-
- return -1;
- }
-
- for (; n < count; n++) {
- if (!mbedtls_mpi_size(mpi[n]))
- continue;
-
- jwk->e[n].buf = lws_malloc(mbedtls_mpi_size(mpi[n]), "certjwk");
- if (!jwk->e[n].buf)
- goto bail;
- jwk->e[n].len = mbedtls_mpi_size(mpi[n]);
- mbedtls_mpi_write_binary(mpi[n], jwk->e[n].buf, jwk->e[n].len);
- }
-
- ret = 0;
-
-bail:
- /* jwk destroy will clean up partials */
- if (ret)
- lws_jwk_destroy(jwk);
-
- return ret;
-}
-
-int
-lws_x509_jwk_privkey_pem(struct lws_jwk *jwk, void *pem, size_t len,
- const char *passphrase)
-{
- mbedtls_rsa_context *rsactx;
- mbedtls_ecp_keypair *ecpctx;
- mbedtls_pk_context pk;
- mbedtls_mpi *mpi[LWS_GENCRYPTO_RSA_KEYEL_COUNT];
- int n, ret = -1, count = 0;
-
- mbedtls_pk_init(&pk);
-
- n = 0;
- if (passphrase)
- n = strlen(passphrase);
- n = mbedtls_pk_parse_key(&pk, pem, len, (uint8_t *)passphrase, n);
- if (n) {
- lwsl_err("%s: parse PEM key failed: -0x%x\n", __func__, -n);
-
- return -1;
- }
-
- /* the incoming private key type */
- switch (mbedtls_pk_get_type(&pk)) {
- case MBEDTLS_PK_RSA:
- if (jwk->kty != LWS_GENCRYPTO_KTY_RSA) {
- lwsl_err("%s: RSA privkey, non-RSA jwk\n", __func__);
- goto bail;
- }
- rsactx = mbedtls_pk_rsa(pk);
- mpi[LWS_GENCRYPTO_RSA_KEYEL_D] = &rsactx->D;
- mpi[LWS_GENCRYPTO_RSA_KEYEL_P] = &rsactx->P;
- mpi[LWS_GENCRYPTO_RSA_KEYEL_Q] = &rsactx->Q;
- n = LWS_GENCRYPTO_RSA_KEYEL_D;
- count = LWS_GENCRYPTO_RSA_KEYEL_Q + 1;
- break;
- case MBEDTLS_PK_ECKEY:
- if (jwk->kty != LWS_GENCRYPTO_KTY_EC) {
- lwsl_err("%s: EC privkey, non-EC jwk\n", __func__);
- goto bail;
- }
- ecpctx = mbedtls_pk_ec(pk);
- mpi[LWS_GENCRYPTO_EC_KEYEL_D] = &ecpctx->d;
- n = LWS_GENCRYPTO_EC_KEYEL_D;
- count = n + 1;
- break;
- default:
- lwsl_err("%s: unusable key type %d\n", __func__,
- mbedtls_pk_get_type(&pk));
- goto bail;
- }
-
- for (; n < count; n++) {
- if (!mbedtls_mpi_size(mpi[n])) {
- lwsl_err("%s: empty privkey\n", __func__);
- goto bail;
- }
-
- jwk->e[n].buf = lws_malloc(mbedtls_mpi_size(mpi[n]), "certjwk");
- if (!jwk->e[n].buf)
- goto bail;
- jwk->e[n].len = mbedtls_mpi_size(mpi[n]);
- mbedtls_mpi_write_binary(mpi[n], jwk->e[n].buf, jwk->e[n].len);
- }
-
- ret = 0;
-
-bail:
- mbedtls_pk_free(&pk);
-
- return ret;
-}
-#endif
-
-void
-lws_x509_destroy(struct lws_x509_cert **x509)
-{
- if (!*x509)
- return;
-
- mbedtls_x509_crt_free(&(*x509)->cert);
-
- lws_free_set_NULL(*x509);
-}
* lws_genaes provides an AES abstraction api in lws that works the
* same whether you are using openssl or mbedtls hash functions underneath.
*/
-#include "core/private.h"
-#include "../../jose/private.h"
+#include "private-lib-core.h"
+#include "../../jose/private-lib-jose.h"
/*
* Care: many openssl apis return 1 for success. These are translated to the
* lws-gencrypto openssl-specific common code
*/
-#include "core/private.h"
-#include "tls/openssl/private.h"
+#include "private-lib-core.h"
+#include "private-lib-tls-openssl.h"
/*
* Care: many openssl apis return 1 for success. These are translated to the
* lws_genec provides an EC abstraction api in lws that works the
* same whether you are using openssl or mbedtls crypto functions underneath.
*/
-#include "core/private.h"
-#include "tls/openssl/private.h"
+#include "private-lib-core.h"
+#include "private-lib-tls-openssl.h"
/*
* Care: many openssl apis return 1 for success. These are translated to the
* lws_genrsa provides an RSA abstraction api in lws that works the
* same whether you are using openssl or mbedtls crypto functions underneath.
*/
-#include "core/private.h"
-#include "tls/openssl/private.h"
+#include "private-lib-core.h"
+#include "private-lib-tls-openssl.h"
/*
* Care: many openssl apis return 1 for success. These are translated to the
* MA 02110-1301 USA
*/
-#include "core/private.h"
-
-#include "tls/openssl/private.h"
+#include "private-lib-core.h"
+#include "private-lib-tls-openssl.h"
/*
* Care: many openssl apis return 1 for success. These are translated to the
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
/*
* Care: many openssl apis return 1 for success. These are translated to the
--- /dev/null
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010-2018 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
+ */
+
+#include "private-lib-core.h"
+#include "private-lib-tls-openssl.h"
+#include <errno.h>
+
+int openssl_websocket_private_data_index,
+ openssl_SSL_CTX_private_data_index;
+
+/*
+ * Care: many openssl apis return 1 for success. These are translated to the
+ * lws convention of 0 for success.
+ */
+
+int lws_openssl_describe_cipher(struct lws *wsi)
+{
+#if !defined(LWS_WITH_NO_LOGS)
+ int np = -1;
+ SSL *s = wsi->tls.ssl;
+
+ SSL_get_cipher_bits(s, &np);
+ lwsl_info("%s: wsi %p: %s, %s, %d bits, %s\n", __func__, wsi,
+ SSL_get_cipher_name(s), SSL_get_cipher(s), np,
+ SSL_get_cipher_version(s));
+#endif
+
+ return 0;
+}
+
+int lws_ssl_get_error(struct lws *wsi, int n)
+{
+ int m;
+
+ if (!wsi->tls.ssl)
+ return 99;
+
+ m = SSL_get_error(wsi->tls.ssl, n);
+ lwsl_debug("%s: %p %d -> %d (errno %d)\n", __func__, wsi->tls.ssl, n, m,
+ errno);
+
+ return m;
+}
+
+static int
+lws_context_init_ssl_pem_passwd_cb(char *buf, int size, int rwflag,
+ void *userdata)
+{
+ struct lws_context_creation_info * info =
+ (struct lws_context_creation_info *)userdata;
+
+ strncpy(buf, info->ssl_private_key_password, size);
+ buf[size - 1] = '\0';
+
+ return (int)strlen(buf);
+}
+
+static int
+lws_context_init_ssl_pem_passwd_client_cb(char *buf, int size, int rwflag,
+ void *userdata)
+{
+ struct lws_context_creation_info * info =
+ (struct lws_context_creation_info *)userdata;
+ const char *p = info->ssl_private_key_password;
+
+ if (info->client_ssl_private_key_password)
+ p = info->client_ssl_private_key_password;
+
+ strncpy(buf, p, size);
+ buf[size - 1] = '\0';
+
+ return (int)strlen(buf);
+}
+
+void
+lws_ssl_bind_passphrase(SSL_CTX *ssl_ctx, int is_client,
+ const struct lws_context_creation_info *info)
+{
+ if (!info->ssl_private_key_password &&
+ !info->client_ssl_private_key_password)
+ return;
+ /*
+ * password provided, set ssl callback and user data
+ * for checking password which will be trigered during
+ * SSL_CTX_use_PrivateKey_file function
+ */
+ SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, (void *)info);
+ SSL_CTX_set_default_passwd_cb(ssl_ctx, is_client ?
+ lws_context_init_ssl_pem_passwd_client_cb:
+ lws_context_init_ssl_pem_passwd_cb);
+}
+
+static void
+lws_ssl_destroy_client_ctx(struct lws_vhost *vhost)
+{
+ struct lws_tls_client_reuse *tcr;
+
+ if (vhost->tls.user_supplied_ssl_ctx || !vhost->tls.ssl_client_ctx)
+ return;
+
+ tcr = SSL_CTX_get_ex_data(vhost->tls.ssl_client_ctx,
+ openssl_SSL_CTX_private_data_index);
+
+ if (!tcr || --tcr->refcount)
+ return;
+
+ SSL_CTX_free(vhost->tls.ssl_client_ctx);
+ vhost->tls.ssl_client_ctx = NULL;
+
+ vhost->context->tls.count_client_contexts--;
+
+ lws_dll2_remove(&tcr->cc_list);
+ lws_free(tcr);
+}
+
+LWS_VISIBLE void
+lws_ssl_destroy(struct lws_vhost *vhost)
+{
+ if (!lws_check_opt(vhost->context->options,
+ LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT))
+ return;
+
+ if (vhost->tls.ssl_ctx)
+ SSL_CTX_free(vhost->tls.ssl_ctx);
+
+ lws_ssl_destroy_client_ctx(vhost);
+
+// after 1.1.0 no need
+#if (OPENSSL_VERSION_NUMBER < 0x10100000)
+// <= 1.0.1f = old api, 1.0.1g+ = new api
+#if (OPENSSL_VERSION_NUMBER <= 0x1000106f) || defined(USE_WOLFSSL)
+ ERR_remove_state(0);
+#else
+#if OPENSSL_VERSION_NUMBER >= 0x1010005f && \
+ !defined(LIBRESSL_VERSION_NUMBER) && \
+ !defined(OPENSSL_IS_BORINGSSL)
+ ERR_remove_thread_state();
+#else
+ ERR_remove_thread_state(NULL);
+#endif
+#endif
+ /* not needed after 1.1.0 */
+#if (OPENSSL_VERSION_NUMBER >= 0x10002000) && \
+ (OPENSSL_VERSION_NUMBER <= 0x10100000)
+ SSL_COMP_free_compression_methods();
+#endif
+ ERR_free_strings();
+ EVP_cleanup();
+ CRYPTO_cleanup_all_ex_data();
+#endif
+}
+
+LWS_VISIBLE int
+lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len)
+{
+ struct lws_context *context = wsi->context;
+ struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
+ int n = 0, m;
+
+ if (!wsi->tls.ssl)
+ return lws_ssl_capable_read_no_ssl(wsi, buf, len);
+
+ lws_stats_bump(pt, LWSSTATS_C_API_READ, 1);
+
+ errno = 0;
+ ERR_clear_error();
+ n = SSL_read(wsi->tls.ssl, buf, len);
+#if defined(LWS_WITH_ESP32)
+ if (!n && errno == LWS_ENOTCONN) {
+ lwsl_debug("%p: SSL_read ENOTCONN\n", wsi);
+ return LWS_SSL_CAPABLE_ERROR;
+ }
+#endif
+#if defined(LWS_WITH_STATS)
+ if (!wsi->seen_rx && wsi->accept_start_us) {
+ lws_stats_bump(pt, LWSSTATS_US_SSL_RX_DELAY_AVG,
+ lws_now_usecs() -
+ wsi->accept_start_us);
+ lws_stats_bump(pt, LWSSTATS_C_SSL_CONNS_HAD_RX, 1);
+ wsi->seen_rx = 1;
+ }
+#endif
+
+
+ lwsl_debug("%p: SSL_read says %d\n", wsi, n);
+ /* manpage: returning 0 means connection shut down
+ *
+ * 2018-09-10: https://github.com/openssl/openssl/issues/1903
+ *
+ * So, in summary, if you get a 0 or -1 return from SSL_read() /
+ * SSL_write(), you should call SSL_get_error():
+ *
+ * - If you get back SSL_ERROR_RETURN_ZERO then you know the connection
+ * has been cleanly shutdown by the peer. To fully close the
+ * connection you may choose to call SSL_shutdown() to send a
+ * close_notify back.
+ *
+ * - If you get back SSL_ERROR_SSL then some kind of internal or
+ * protocol error has occurred. More details will be on the SSL error
+ * queue. You can also call SSL_get_shutdown(). If this indicates a
+ * state of SSL_RECEIVED_SHUTDOWN then you know a fatal alert has
+ * been received from the peer (if it had been a close_notify then
+ * SSL_get_error() would have returned SSL_ERROR_RETURN_ZERO).
+ * SSL_ERROR_SSL is considered fatal - you should not call
+ * SSL_shutdown() in this case.
+ *
+ * - If you get back SSL_ERROR_SYSCALL then some kind of fatal (i.e.
+ * non-retryable) error has occurred in a system call.
+ */
+ if (n <= 0) {
+ m = lws_ssl_get_error(wsi, n);
+ lwsl_debug("%p: ssl err %d errno %d\n", wsi, m, errno);
+ if (m == SSL_ERROR_ZERO_RETURN) /* cleanly shut down */
+ return LWS_SSL_CAPABLE_ERROR;
+
+ /* hm not retryable.. could be 0 size pkt or error */
+
+ if (m == SSL_ERROR_SSL || m == SSL_ERROR_SYSCALL ||
+ errno == LWS_ENOTCONN) {
+
+ /* unclean, eg closed conn */
+
+ wsi->socket_is_permanently_unusable = 1;
+
+ return LWS_SSL_CAPABLE_ERROR;
+ }
+
+ /* retryable? */
+
+ if (SSL_want_read(wsi->tls.ssl)) {
+ lwsl_debug("%s: WANT_READ\n", __func__);
+ lwsl_debug("%p: LWS_SSL_CAPABLE_MORE_SERVICE\n", wsi);
+ return LWS_SSL_CAPABLE_MORE_SERVICE;
+ }
+ if (SSL_want_write(wsi->tls.ssl)) {
+ lwsl_debug("%s: WANT_WRITE\n", __func__);
+ lwsl_debug("%p: LWS_SSL_CAPABLE_MORE_SERVICE\n", wsi);
+ return LWS_SSL_CAPABLE_MORE_SERVICE;
+ }
+
+ /* keep on trucking it seems */
+ }
+
+ lws_stats_bump(pt, LWSSTATS_B_READ, n);
+
+ if (wsi->vhost)
+ wsi->vhost->conn_stats.rx += n;
+
+ // lwsl_hexdump_err(buf, n);
+
+ /*
+ * if it was our buffer that limited what we read,
+ * check if SSL has additional data pending inside SSL buffers.
+ *
+ * Because these won't signal at the network layer with POLLIN
+ * and if we don't realize, this data will sit there forever
+ */
+ if (n != len)
+ goto bail;
+ if (!wsi->tls.ssl)
+ goto bail;
+
+ if (SSL_pending(wsi->tls.ssl) &&
+ lws_dll2_is_detached(&wsi->tls.dll_pending_tls))
+ lws_dll2_add_head(&wsi->tls.dll_pending_tls,
+ &pt->tls.dll_pending_tls_owner);
+
+ return n;
+bail:
+ lws_ssl_remove_wsi_from_buffered_list(wsi);
+
+ return n;
+}
+
+LWS_VISIBLE int
+lws_ssl_pending(struct lws *wsi)
+{
+ if (!wsi->tls.ssl)
+ return 0;
+
+ return SSL_pending(wsi->tls.ssl);
+}
+
+LWS_VISIBLE int
+lws_ssl_capable_write(struct lws *wsi, unsigned char *buf, int len)
+{
+ int n, m;
+
+ if (!wsi->tls.ssl)
+ return lws_ssl_capable_write_no_ssl(wsi, buf, len);
+
+ errno = 0;
+ ERR_clear_error();
+ n = SSL_write(wsi->tls.ssl, buf, len);
+ if (n > 0)
+ return n;
+
+ m = lws_ssl_get_error(wsi, n);
+ if (m != SSL_ERROR_SYSCALL) {
+ if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) {
+ lwsl_notice("%s: want read\n", __func__);
+
+ return LWS_SSL_CAPABLE_MORE_SERVICE;
+ }
+
+ if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) {
+ lws_set_blocking_send(wsi);
+
+ lwsl_debug("%s: want write\n", __func__);
+
+ return LWS_SSL_CAPABLE_MORE_SERVICE;
+ }
+ }
+
+ lwsl_debug("%s failed: %s\n",__func__, ERR_error_string(m, NULL));
+ lws_tls_err_describe_clear();
+
+ wsi->socket_is_permanently_unusable = 1;
+
+ return LWS_SSL_CAPABLE_ERROR;
+}
+
+void
+lws_ssl_info_callback(const SSL *ssl, int where, int ret)
+{
+ struct lws *wsi;
+ struct lws_context *context;
+ struct lws_ssl_info si;
+
+#ifndef USE_WOLFSSL
+ context = (struct lws_context *)SSL_CTX_get_ex_data(
+ SSL_get_SSL_CTX(ssl),
+ openssl_SSL_CTX_private_data_index);
+#else
+ context = (struct lws_context *)SSL_CTX_get_ex_data(
+ SSL_get_SSL_CTX((SSL*) ssl),
+ openssl_SSL_CTX_private_data_index);
+#endif
+ if (!context)
+ return;
+ wsi = wsi_from_fd(context, SSL_get_fd(ssl));
+ if (!wsi)
+ return;
+
+ if (!(where & wsi->vhost->tls.ssl_info_event_mask))
+ return;
+
+ si.where = where;
+ si.ret = ret;
+
+ if (user_callback_handle_rxflow(wsi->protocol->callback,
+ wsi, LWS_CALLBACK_SSL_INFO,
+ wsi->user_space, &si, 0))
+ lws_set_timeout(wsi, PENDING_TIMEOUT_KILLED_BY_SSL_INFO, -1);
+}
+
+
+LWS_VISIBLE int
+lws_ssl_close(struct lws *wsi)
+{
+ lws_sockfd_type n;
+
+ if (!wsi->tls.ssl)
+ return 0; /* not handled */
+
+#if defined (LWS_HAVE_SSL_SET_INFO_CALLBACK)
+ /* kill ssl callbacks, because we will remove the fd from the
+ * table linking it to the wsi
+ */
+ if (wsi->vhost->tls.ssl_info_event_mask)
+ SSL_set_info_callback(wsi->tls.ssl, NULL);
+#endif
+
+ n = SSL_get_fd(wsi->tls.ssl);
+ if (!wsi->socket_is_permanently_unusable)
+ SSL_shutdown(wsi->tls.ssl);
+ compatible_close(n);
+ SSL_free(wsi->tls.ssl);
+ wsi->tls.ssl = NULL;
+
+ if (wsi->context->simultaneous_ssl_restriction &&
+ wsi->context->simultaneous_ssl-- ==
+ wsi->context->simultaneous_ssl_restriction)
+ /* we made space and can do an accept */
+ lws_gate_accepts(wsi->context, 1);
+
+ // lwsl_notice("%s: ssl restr %d, simul %d\n", __func__,
+ // wsi->context->simultaneous_ssl_restriction,
+ // wsi->context->simultaneous_ssl);
+
+#if defined(LWS_WITH_STATS)
+ wsi->context->updated = 1;
+#endif
+
+ return 1; /* handled */
+}
+
+void
+lws_ssl_SSL_CTX_destroy(struct lws_vhost *vhost)
+{
+ if (vhost->tls.ssl_ctx)
+ SSL_CTX_free(vhost->tls.ssl_ctx);
+
+ lws_ssl_destroy_client_ctx(vhost);
+
+#if defined(LWS_WITH_ACME)
+ lws_tls_acme_sni_cert_destroy(vhost);
+#endif
+}
+
+void
+lws_ssl_context_destroy(struct lws_context *context)
+{
+// after 1.1.0 no need
+#if (OPENSSL_VERSION_NUMBER < 0x10100000)
+// <= 1.0.1f = old api, 1.0.1g+ = new api
+#if (OPENSSL_VERSION_NUMBER <= 0x1000106f) || defined(USE_WOLFSSL)
+ ERR_remove_state(0);
+#else
+#if OPENSSL_VERSION_NUMBER >= 0x1010005f && \
+ !defined(LIBRESSL_VERSION_NUMBER) && \
+ !defined(OPENSSL_IS_BORINGSSL)
+ ERR_remove_thread_state();
+#else
+ ERR_remove_thread_state(NULL);
+#endif
+#endif
+ // after 1.1.0 no need
+#if (OPENSSL_VERSION_NUMBER >= 0x10002000) && (OPENSSL_VERSION_NUMBER <= 0x10100000)
+ SSL_COMP_free_compression_methods();
+#endif
+ ERR_free_strings();
+ EVP_cleanup();
+ CRYPTO_cleanup_all_ex_data();
+#endif
+}
+
+lws_tls_ctx *
+lws_tls_ctx_from_wsi(struct lws *wsi)
+{
+ if (!wsi->tls.ssl)
+ return NULL;
+
+ return SSL_get_SSL_CTX(wsi->tls.ssl);
+}
+
+enum lws_ssl_capable_status
+__lws_tls_shutdown(struct lws *wsi)
+{
+ int n;
+
+ errno = 0;
+ ERR_clear_error();
+ n = SSL_shutdown(wsi->tls.ssl);
+ lwsl_debug("SSL_shutdown=%d for fd %d\n", n, wsi->desc.sockfd);
+ switch (n) {
+ case 1: /* successful completion */
+ n = shutdown(wsi->desc.sockfd, SHUT_WR);
+ return LWS_SSL_CAPABLE_DONE;
+
+ case 0: /* needs a retry */
+ __lws_change_pollfd(wsi, 0, LWS_POLLIN);
+ return LWS_SSL_CAPABLE_MORE_SERVICE;
+
+ default: /* fatal error, or WANT */
+ n = SSL_get_error(wsi->tls.ssl, n);
+ if (n != SSL_ERROR_SYSCALL && n != SSL_ERROR_SSL) {
+ if (SSL_want_read(wsi->tls.ssl)) {
+ lwsl_debug("(wants read)\n");
+ __lws_change_pollfd(wsi, 0, LWS_POLLIN);
+ return LWS_SSL_CAPABLE_MORE_SERVICE_READ;
+ }
+ if (SSL_want_write(wsi->tls.ssl)) {
+ lwsl_debug("(wants write)\n");
+ __lws_change_pollfd(wsi, 0, LWS_POLLOUT);
+ return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE;
+ }
+ }
+ return LWS_SSL_CAPABLE_ERROR;
+ }
+}
+
+
+static int
+tops_fake_POLLIN_for_buffered_openssl(struct lws_context_per_thread *pt)
+{
+ return lws_tls_fake_POLLIN_for_buffered(pt);
+}
+
+const struct lws_tls_ops tls_ops_openssl = {
+ /* fake_POLLIN_for_buffered */ tops_fake_POLLIN_for_buffered_openssl,
+};
--- /dev/null
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010-2018 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
+ */
+
+#include "private-lib-core.h"
+#include "private-lib-tls-openssl.h"
+
+extern int openssl_websocket_private_data_index,
+openssl_SSL_CTX_private_data_index;
+
+char* lws_ssl_get_error_string(int status, int ret, char *buf, size_t len) {
+ switch (status) {
+ case SSL_ERROR_NONE:
+ return lws_strncpy(buf, "SSL_ERROR_NONE", len);
+ case SSL_ERROR_ZERO_RETURN:
+ return lws_strncpy(buf, "SSL_ERROR_ZERO_RETURN", len);
+ case SSL_ERROR_WANT_READ:
+ return lws_strncpy(buf, "SSL_ERROR_WANT_READ", len);
+ case SSL_ERROR_WANT_WRITE:
+ return lws_strncpy(buf, "SSL_ERROR_WANT_WRITE", len);
+ case SSL_ERROR_WANT_CONNECT:
+ return lws_strncpy(buf, "SSL_ERROR_WANT_CONNECT", len);
+ case SSL_ERROR_WANT_ACCEPT:
+ return lws_strncpy(buf, "SSL_ERROR_WANT_ACCEPT", len);
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ return lws_strncpy(buf, "SSL_ERROR_WANT_X509_LOOKUP", len);
+ case SSL_ERROR_SYSCALL:
+ switch (ret) {
+ case 0:
+ lws_snprintf(buf, len, "SSL_ERROR_SYSCALL: EOF");
+ return buf;
+ case -1:
+#ifndef LWS_PLAT_OPTEE
+ lws_snprintf(buf, len, "SSL_ERROR_SYSCALL: %s",
+ strerror(errno));
+#else
+ lws_snprintf(buf, len, "SSL_ERROR_SYSCALL: %d", errno);
+#endif
+ return buf;
+ default:
+ return strncpy(buf, "SSL_ERROR_SYSCALL", len);
+ }
+ case SSL_ERROR_SSL:
+ return "SSL_ERROR_SSL";
+ default:
+ return "SSL_ERROR_UNKNOWN";
+ }
+}
+
+void
+lws_tls_err_describe_clear(void)
+{
+ char buf[160];
+ unsigned long l;
+
+ do {
+ l = ERR_get_error();
+ if (!l)
+ break;
+
+ ERR_error_string_n(l, buf, sizeof(buf));
+ lwsl_info(" openssl error: %s\n", buf);
+ } while (l);
+ lwsl_info("\n");
+}
+
+#if LWS_MAX_SMP != 1
+
+static pthread_mutex_t *openssl_mutexes;
+
+static void
+lws_openssl_lock_callback(int mode, int type, const char *file, int line)
+{
+ (void)file;
+ (void)line;
+
+ if (mode & CRYPTO_LOCK)
+ pthread_mutex_lock(&openssl_mutexes[type]);
+ else
+ pthread_mutex_unlock(&openssl_mutexes[type]);
+}
+
+static unsigned long
+lws_openssl_thread_id(void)
+{
+ return (unsigned long)pthread_self();
+}
+#endif
+
+
+int
+lws_context_init_ssl_library(const struct lws_context_creation_info *info)
+{
+#ifdef USE_WOLFSSL
+#ifdef USE_OLD_CYASSL
+ lwsl_info(" Compiled with CyaSSL support\n");
+#else
+ lwsl_info(" Compiled with wolfSSL support\n");
+#endif
+#else
+#if defined(LWS_WITH_BORINGSSL)
+ lwsl_info(" Compiled with BoringSSL support\n");
+#else
+ lwsl_info(" Compiled with OpenSSL support\n");
+#endif
+#endif
+ if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT)) {
+ lwsl_info(" SSL disabled: no "
+ "LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT\n");
+ return 0;
+ }
+
+ /* basic openssl init */
+
+ lwsl_info("Doing SSL library init\n");
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+ SSL_library_init();
+ OpenSSL_add_all_algorithms();
+ SSL_load_error_strings();
+#else
+ OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
+#endif
+#if defined(LWS_WITH_NETWORK)
+ openssl_websocket_private_data_index =
+ SSL_get_ex_new_index(0, "lws", NULL, NULL, NULL);
+
+ openssl_SSL_CTX_private_data_index = SSL_CTX_get_ex_new_index(0,
+ NULL, NULL, NULL, NULL);
+#endif
+
+#if LWS_MAX_SMP != 1
+ {
+ int n;
+
+ openssl_mutexes = (pthread_mutex_t *)
+ OPENSSL_malloc(CRYPTO_num_locks() *
+ sizeof(openssl_mutexes[0]));
+
+ for (n = 0; n < CRYPTO_num_locks(); n++)
+ pthread_mutex_init(&openssl_mutexes[n], NULL);
+
+ /*
+ * These "functions" disappeared in later OpenSSL which is
+ * already threadsafe.
+ */
+
+ (void)lws_openssl_thread_id;
+ (void)lws_openssl_lock_callback;
+
+ CRYPTO_set_id_callback(lws_openssl_thread_id);
+ CRYPTO_set_locking_callback(lws_openssl_lock_callback);
+ }
+#endif
+
+ return 0;
+}
+
+void
+lws_context_deinit_ssl_library(struct lws_context *context)
+{
+#if LWS_MAX_SMP != 1
+ int n;
+
+ if (!lws_check_opt(context->options,
+ LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT))
+ return;
+
+ CRYPTO_set_locking_callback(NULL);
+
+ for (n = 0; n < CRYPTO_num_locks(); n++)
+ pthread_mutex_destroy(&openssl_mutexes[n]);
+
+ OPENSSL_free(openssl_mutexes);
+#endif
+}
--- /dev/null
+/*
+ * libwebsockets - OpenSSL-specific lws apis
+ *
+ * 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
+ */
+
+#include "private-lib-core.h"
+#include "private-lib-tls-openssl.h"
+
+#if !defined(LWS_PLAT_OPTEE)
+static int
+dec(char c)
+{
+ return c - '0';
+}
+#endif
+
+static time_t
+lws_tls_openssl_asn1time_to_unix(ASN1_TIME *as)
+{
+#if !defined(LWS_PLAT_OPTEE)
+
+ const char *p = (const char *)as->data;
+ struct tm t;
+
+ /* [YY]YYMMDDHHMMSSZ */
+
+ memset(&t, 0, sizeof(t));
+
+ if (strlen(p) == 13) {
+ t.tm_year = (dec(p[0]) * 10) + dec(p[1]) + 100;
+ p += 2;
+ } else {
+ t.tm_year = (dec(p[0]) * 1000) + (dec(p[1]) * 100) +
+ (dec(p[2]) * 10) + dec(p[3]);
+ p += 4;
+ }
+ t.tm_mon = (dec(p[0]) * 10) + dec(p[1]) - 1;
+ p += 2;
+ t.tm_mday = (dec(p[0]) * 10) + dec(p[1]) - 1;
+ p += 2;
+ t.tm_hour = (dec(p[0]) * 10) + dec(p[1]);
+ p += 2;
+ t.tm_min = (dec(p[0]) * 10) + dec(p[1]);
+ p += 2;
+ t.tm_sec = (dec(p[0]) * 10) + dec(p[1]);
+ t.tm_isdst = 0;
+
+ return mktime(&t);
+#else
+ return (time_t)-1;
+#endif
+}
+
+int
+lws_tls_openssl_cert_info(X509 *x509, enum lws_tls_cert_info type,
+ union lws_tls_cert_info_results *buf, size_t len)
+{
+ X509_NAME *xn;
+#if !defined(LWS_PLAT_OPTEE)
+ char *p;
+#endif
+
+ if (!x509)
+ return -1;
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(X509_get_notBefore)
+#define X509_get_notBefore(x) X509_getm_notBefore(x)
+#define X509_get_notAfter(x) X509_getm_notAfter(x)
+#endif
+
+ switch (type) {
+ case LWS_TLS_CERT_INFO_VALIDITY_FROM:
+ buf->time = lws_tls_openssl_asn1time_to_unix(
+ X509_get_notBefore(x509));
+ if (buf->time == (time_t)-1)
+ return -1;
+ break;
+
+ case LWS_TLS_CERT_INFO_VALIDITY_TO:
+ buf->time = lws_tls_openssl_asn1time_to_unix(
+ X509_get_notAfter(x509));
+ if (buf->time == (time_t)-1)
+ return -1;
+ break;
+
+ case LWS_TLS_CERT_INFO_COMMON_NAME:
+#if defined(LWS_PLAT_OPTEE)
+ return -1;
+#else
+ xn = X509_get_subject_name(x509);
+ if (!xn)
+ return -1;
+ X509_NAME_oneline(xn, buf->ns.name, (int)len - 2);
+ p = strstr(buf->ns.name, "/CN=");
+ if (p)
+ memmove(buf->ns.name, p + 4, strlen(p + 4) + 1);
+ buf->ns.len = (int)strlen(buf->ns.name);
+ return 0;
+#endif
+ case LWS_TLS_CERT_INFO_ISSUER_NAME:
+ xn = X509_get_issuer_name(x509);
+ if (!xn)
+ return -1;
+ X509_NAME_oneline(xn, buf->ns.name, (int)len - 1);
+ buf->ns.len = (int)strlen(buf->ns.name);
+ return 0;
+
+ case LWS_TLS_CERT_INFO_USAGE:
+#if defined(LWS_HAVE_X509_get_key_usage)
+ buf->usage = X509_get_key_usage(x509);
+ break;
+#else
+ return -1;
+#endif
+
+ case LWS_TLS_CERT_INFO_OPAQUE_PUBLIC_KEY:
+ {
+#ifndef USE_WOLFSSL
+ size_t klen = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x509), NULL);
+ uint8_t *tmp, *ptmp;
+
+ if (!klen || klen > len)
+ return -1;
+
+ tmp = (uint8_t *)OPENSSL_malloc(klen);
+ if (!tmp)
+ return -1;
+
+ ptmp = tmp;
+ if (i2d_X509_PUBKEY(
+ X509_get_X509_PUBKEY(x509), &ptmp) != (int)klen ||
+ !ptmp || lws_ptr_diff(ptmp, tmp) != (int)klen) {
+ lwsl_info("%s: cert public key extraction failed\n",
+ __func__);
+ if (ptmp)
+ OPENSSL_free(tmp);
+
+ return -1;
+ }
+
+ buf->ns.len = (int)klen;
+ memcpy(buf->ns.name, tmp, klen);
+ OPENSSL_free(tmp);
+#endif
+ return 0;
+ }
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+lws_x509_info(struct lws_x509_cert *x509, enum lws_tls_cert_info type,
+ union lws_tls_cert_info_results *buf, size_t len)
+{
+ return lws_tls_openssl_cert_info(x509->cert, type, buf, len);
+}
+
+#if defined(LWS_WITH_NETWORK)
+int
+lws_tls_vhost_cert_info(struct lws_vhost *vhost, enum lws_tls_cert_info type,
+ union lws_tls_cert_info_results *buf, size_t len)
+{
+#if defined(LWS_HAVE_SSL_CTX_get0_certificate)
+ X509 *x509 = SSL_CTX_get0_certificate(vhost->tls.ssl_ctx);
+
+ return lws_tls_openssl_cert_info(x509, type, buf, len);
+#else
+ lwsl_notice("openssl is too old to support %s\n", __func__);
+
+ return -1;
+#endif
+}
+
+
+
+int
+lws_tls_peer_cert_info(struct lws *wsi, enum lws_tls_cert_info type,
+ union lws_tls_cert_info_results *buf, size_t len)
+{
+ int rc = 0;
+ X509 *x509;
+
+ wsi = lws_get_network_wsi(wsi);
+
+ x509 = SSL_get_peer_certificate(wsi->tls.ssl);
+
+ if (!x509) {
+ lwsl_debug("no peer cert\n");
+
+ return -1;
+ }
+
+ switch (type) {
+ case LWS_TLS_CERT_INFO_VERIFIED:
+ buf->verified = SSL_get_verify_result(wsi->tls.ssl) ==
+ X509_V_OK;
+ break;
+ default:
+ rc = lws_tls_openssl_cert_info(x509, type, buf, len);
+ }
+
+ X509_free(x509);
+
+ return rc;
+}
+#endif
+
+int
+lws_x509_create(struct lws_x509_cert **x509)
+{
+ *x509 = lws_malloc(sizeof(**x509), __func__);
+ if (*x509)
+ (*x509)->cert = NULL;
+
+ return !(*x509);
+}
+
+int
+lws_x509_parse_from_pem(struct lws_x509_cert *x509, const void *pem, size_t len)
+{
+ BIO* bio = BIO_new(BIO_s_mem());
+
+ BIO_write(bio, pem, len);
+ x509->cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
+ BIO_free(bio);
+ if (!x509->cert) {
+ lwsl_err("%s: unable to parse PEM cert\n", __func__);
+ lws_tls_err_describe_clear();
+
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+lws_x509_verify(struct lws_x509_cert *x509, struct lws_x509_cert *trusted,
+ const char *common_name)
+{
+ char c[32], *p;
+ int ret;
+
+ if (common_name) {
+ X509_NAME *xn = X509_get_subject_name(x509->cert);
+ if (!xn)
+ return -1;
+ X509_NAME_oneline(xn, c, (int)sizeof(c) - 2);
+ p = strstr(c, "/CN=");
+ if (p)
+ p = p + 4;
+ else
+ p = c;
+
+ if (strcmp(p, common_name)) {
+ lwsl_err("%s: common name mismatch\n", __func__);
+ return -1;
+ }
+ }
+
+ ret = X509_check_issued(trusted->cert, x509->cert);
+ if (ret != X509_V_OK) {
+ lwsl_err("%s: unable to verify cert relationship\n", __func__);
+ lws_tls_err_describe_clear();
+
+ return -1;
+ }
+
+ return 0;
+}
+
+#if defined(LWS_WITH_JOSE)
+int
+lws_x509_public_to_jwk(struct lws_jwk *jwk, struct lws_x509_cert *x509,
+ const char *curves, int rsa_min_bits)
+{
+ int id, n, ret = -1, count;
+ ASN1_OBJECT *obj = NULL;
+ const EC_POINT *ecpoint;
+ const EC_GROUP *ecgroup;
+ EC_KEY *ecpub = NULL;
+ X509_PUBKEY *pubkey;
+ RSA *rsapub = NULL;
+ BIGNUM *mpi[4];
+ EVP_PKEY *pkey;
+
+ memset(jwk, 0, sizeof(*jwk));
+
+ pubkey = X509_get_X509_PUBKEY(x509->cert);
+ if (!pubkey) {
+ lwsl_err("%s: missing pubkey alg in cert\n", __func__);
+
+ goto bail;
+ }
+
+ if (X509_PUBKEY_get0_param(&obj, NULL, NULL, NULL, pubkey) != 1) {
+ lwsl_err("%s: missing pubkey alg in cert\n", __func__);
+
+ goto bail;
+ }
+
+ id = OBJ_obj2nid(obj);
+ if (id == NID_undef) {
+ lwsl_err("%s: missing pubkey alg in cert\n", __func__);
+
+ goto bail;
+ }
+
+ lwsl_debug("%s: key type %d \"%s\"\n", __func__, id, OBJ_nid2ln(id));
+
+ pkey = X509_get_pubkey(x509->cert);
+ if (!pkey) {
+ lwsl_notice("%s: unable to extract pubkey", __func__);
+
+ goto bail;
+ }
+
+ switch (id) {
+ case NID_X9_62_id_ecPublicKey:
+ lwsl_debug("%s: EC key\n", __func__);
+ jwk->kty = LWS_GENCRYPTO_KTY_EC;
+
+ if (!curves) {
+ lwsl_err("%s: ec curves not allowed\n", __func__);
+
+ goto bail1;
+ }
+
+ ecpub = EVP_PKEY_get1_EC_KEY(pkey);
+ if (!ecpub) {
+ lwsl_notice("%s: missing EC pubkey\n", __func__);
+
+ goto bail1;
+ }
+
+ ecpoint = EC_KEY_get0_public_key(ecpub);
+ if (!ecpoint) {
+ lwsl_err("%s: EC_KEY_get0_public_key failed\n", __func__);
+ goto bail2;
+ }
+
+ ecgroup = EC_KEY_get0_group(ecpub);
+ if (!ecgroup) {
+ lwsl_err("%s: EC_KEY_get0_group failed\n", __func__);
+ goto bail2;
+ }
+
+ /* validate the curve against ones we allow */
+
+ if (lws_genec_confirm_curve_allowed_by_tls_id(curves,
+ EC_GROUP_get_curve_name(ecgroup), jwk))
+ /* already logged */
+ goto bail2;
+
+ mpi[LWS_GENCRYPTO_EC_KEYEL_CRV] = NULL;
+ mpi[LWS_GENCRYPTO_EC_KEYEL_X] = BN_new(); /* X */
+ mpi[LWS_GENCRYPTO_EC_KEYEL_D] = NULL;
+ mpi[LWS_GENCRYPTO_EC_KEYEL_Y] = BN_new(); /* Y */
+
+#if defined(LWS_HAVE_EC_POINT_get_affine_coordinates)
+ if (EC_POINT_get_affine_coordinates(ecgroup, ecpoint,
+#else
+ if (EC_POINT_get_affine_coordinates_GFp(ecgroup, ecpoint,
+#endif
+ mpi[LWS_GENCRYPTO_EC_KEYEL_X],
+ mpi[LWS_GENCRYPTO_EC_KEYEL_Y],
+ NULL) != 1) {
+ BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]);
+ BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]);
+ lwsl_err("%s: EC_POINT_get_aff failed\n", __func__);
+ goto bail2;
+ }
+ count = LWS_GENCRYPTO_EC_KEYEL_COUNT;
+ n = LWS_GENCRYPTO_EC_KEYEL_X;
+ break;
+
+ case NID_rsaEncryption:
+ lwsl_debug("%s: rsa key\n", __func__);
+ jwk->kty = LWS_GENCRYPTO_KTY_RSA;
+
+ rsapub = EVP_PKEY_get1_RSA(pkey);
+ if (!rsapub) {
+ lwsl_notice("%s: missing RSA pubkey\n", __func__);
+
+ goto bail1;
+ }
+
+ if ((size_t)RSA_size(rsapub) * 8 < (size_t)rsa_min_bits) {
+ lwsl_err("%s: key bits %d less than minimum %d\n",
+ __func__, RSA_size(rsapub) * 8, rsa_min_bits);
+
+ goto bail2;
+ }
+
+#if defined(LWS_HAVE_RSA_SET0_KEY)
+ /* we don't need d... but the api wants to write it */
+ RSA_get0_key(rsapub,
+ (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_N],
+ (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_E],
+ (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_D]);
+#else
+ mpi[LWS_GENCRYPTO_RSA_KEYEL_E] = rsapub->e;
+ mpi[LWS_GENCRYPTO_RSA_KEYEL_N] = rsapub->n;
+ mpi[LWS_GENCRYPTO_RSA_KEYEL_D] = NULL;
+#endif
+ count = LWS_GENCRYPTO_RSA_KEYEL_D;
+ n = LWS_GENCRYPTO_RSA_KEYEL_E;
+ break;
+ default:
+ lwsl_err("%s: unknown NID\n", __func__);
+ goto bail2;
+ }
+
+ for (; n < count; n++) {
+ if (!mpi[n])
+ continue;
+ jwk->e[n].len = BN_num_bytes(mpi[n]);
+ jwk->e[n].buf = lws_malloc(jwk->e[n].len, "certkeyimp");
+ if (!jwk->e[n].buf) {
+ if (id == NID_X9_62_id_ecPublicKey) {
+ BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]);
+ BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]);
+ }
+ goto bail2;
+ }
+ BN_bn2bin(mpi[n], jwk->e[n].buf);
+ }
+
+ if (id == NID_X9_62_id_ecPublicKey) {
+ BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]);
+ BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]);
+ }
+
+ ret = 0;
+
+bail2:
+ if (id == NID_X9_62_id_ecPublicKey)
+ EC_KEY_free(ecpub);
+ else
+ RSA_free(rsapub);
+
+bail1:
+ EVP_PKEY_free(pkey);
+bail:
+ /* jwk destroy will clean any partial state */
+ if (ret)
+ lws_jwk_destroy(jwk);
+
+ return ret;
+}
+
+static int
+lws_x509_jwk_privkey_pem_pp_cb(char *buf, int size, int rwflag, void *u)
+{
+ const char *pp = (const char *)u;
+ int n = strlen(pp);
+
+ if (n > size - 1)
+ return -1;
+
+ memcpy(buf, pp, n + 1);
+
+ return n;
+}
+
+int
+lws_x509_jwk_privkey_pem(struct lws_jwk *jwk, void *pem, size_t len,
+ const char *passphrase)
+{
+ BIO* bio = BIO_new(BIO_s_mem());
+ BIGNUM *mpi, *dummy[6];
+ EVP_PKEY *pkey = NULL;
+ EC_KEY *ecpriv = NULL;
+ RSA *rsapriv = NULL;
+ const BIGNUM *cmpi;
+ int n, m, ret = -1;
+
+ BIO_write(bio, pem, len);
+ PEM_read_bio_PrivateKey(bio, &pkey, lws_x509_jwk_privkey_pem_pp_cb,
+ (void *)passphrase);
+ BIO_free(bio);
+ lws_explicit_bzero((void *)pem, len);
+ if (!pkey) {
+ lwsl_err("%s: unable to parse PEM privkey\n", __func__);
+ lws_tls_err_describe_clear();
+
+ return -1;
+ }
+
+ /* confirm the key type matches the existing jwk situation */
+
+ switch (jwk->kty) {
+ case LWS_GENCRYPTO_KTY_EC:
+ if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_EC) {
+ lwsl_err("%s: jwk is EC but privkey isn't\n", __func__);
+
+ goto bail;
+ }
+ ecpriv = EVP_PKEY_get1_EC_KEY(pkey);
+ if (!ecpriv) {
+ lwsl_notice("%s: missing EC key\n", __func__);
+
+ goto bail;
+ }
+
+ cmpi = EC_KEY_get0_private_key(ecpriv);
+
+ /* quick size check first */
+
+ n = BN_num_bytes(cmpi);
+ if (jwk->e[LWS_GENCRYPTO_EC_KEYEL_Y].len != (uint32_t)n) {
+ lwsl_err("%s: jwk key size doesn't match\n", __func__);
+
+ goto bail1;
+ }
+
+ /* TODO.. check public curve / group + point */
+
+ jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].len = n;
+ jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf = lws_malloc(n, "ec");
+ if (!jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf)
+ goto bail1;
+
+ m = BN_bn2binpad(cmpi, jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf,
+ jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].len);
+ if ((unsigned int)m != (unsigned int)BN_num_bytes(cmpi))
+ goto bail1;
+
+ break;
+
+ case LWS_GENCRYPTO_KTY_RSA:
+ if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_RSA) {
+ lwsl_err("%s: RSA jwk, non-RSA privkey\n", __func__);
+
+ goto bail;
+ }
+ rsapriv = EVP_PKEY_get1_RSA(pkey);
+ if (!rsapriv) {
+ lwsl_notice("%s: missing RSA key\n", __func__);
+
+ goto bail;
+ }
+
+#if defined(LWS_HAVE_RSA_SET0_KEY)
+ RSA_get0_key(rsapriv, (const BIGNUM **)&dummy[0], /* n */
+ (const BIGNUM **)&dummy[1], /* e */
+ (const BIGNUM **)&mpi); /* d */
+ RSA_get0_factors(rsapriv, (const BIGNUM **)&dummy[4], /* p */
+ (const BIGNUM **)&dummy[5]); /* q */
+#else
+ dummy[0] = rsapriv->n;
+ dummy[1] = rsapriv->e;
+ dummy[4] = rsapriv->p;
+ dummy[5] = rsapriv->q;
+ mpi = rsapriv->d;
+#endif
+
+ /* quick size check first */
+
+ n = BN_num_bytes(mpi);
+ if (jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].len != (uint32_t)n) {
+ lwsl_err("%s: jwk key size doesn't match\n", __func__);
+
+ goto bail1;
+ }
+
+ /* then check that n & e match what we got from the cert */
+
+ dummy[2] = BN_bin2bn(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].buf,
+ jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].len,
+ NULL);
+ dummy[3] = BN_bin2bn(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_E].buf,
+ jwk->e[LWS_GENCRYPTO_RSA_KEYEL_E].len,
+ NULL);
+
+ m = BN_cmp(dummy[2], dummy[0]) | BN_cmp(dummy[3], dummy[1]);
+ BN_clear_free(dummy[2]);
+ BN_clear_free(dummy[3]);
+ if (m) {
+ lwsl_err("%s: privkey doesn't match jwk pubkey\n",
+ __func__);
+
+ goto bail1;
+ }
+
+ /* accept d from the PEM privkey into the JWK */
+
+ jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].len = n;
+ jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf = lws_malloc(n, "privjk");
+ if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf)
+ goto bail1;
+
+ BN_bn2bin(mpi, jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf);
+
+ /* accept p and q from the PEM privkey into the JWK */
+
+ jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].len = BN_num_bytes(dummy[4]);
+ jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf = lws_malloc(n, "privjk");
+ if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf) {
+ lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf);
+ goto bail1;
+ }
+ BN_bn2bin(dummy[4], jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf);
+
+ jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].len = BN_num_bytes(dummy[5]);
+ jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf = lws_malloc(n, "privjk");
+ if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf) {
+ lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf);
+ lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf);
+ goto bail1;
+ }
+ BN_bn2bin(dummy[5], jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf);
+ break;
+ default:
+ lwsl_err("%s: JWK has unknown kty %d\n", __func__, jwk->kty);
+ return -1;
+ }
+
+ ret = 0;
+
+bail1:
+ if (jwk->kty == LWS_GENCRYPTO_KTY_EC)
+ EC_KEY_free(ecpriv);
+ else
+ RSA_free(rsapriv);
+
+bail:
+ EVP_PKEY_free(pkey);
+
+ return ret;
+}
+#endif
+
+void
+lws_x509_destroy(struct lws_x509_cert **x509)
+{
+ if (!*x509)
+ return;
+
+ if ((*x509)->cert) {
+ X509_free((*x509)->cert);
+ (*x509)->cert = NULL;
+ }
+
+ lws_free_set_NULL(*x509);
+}
--- /dev/null
+/*
+ * 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
+ *
+ * gencrypto openssl-specific helper declarations
+ */
+
+/*
+ * one of these per different client context
+ * cc_owner is in lws_context.lws_context_tls
+ */
+
+struct lws_tls_client_reuse {
+ lws_tls_ctx *ssl_client_ctx;
+ uint8_t hash[32];
+ struct lws_dll2 cc_list;
+ int refcount;
+ int index;
+};
+
+typedef int (*next_proto_cb)(SSL *, const unsigned char **out,
+ unsigned char *outlen, const unsigned char *in,
+ unsigned int inlen, void *arg);
+
+struct lws_x509_cert {
+ X509 *cert; /* X509 is opaque, this has to be a pointer */
+};
+
+int
+lws_gencrypto_openssl_hash_to_NID(enum lws_genhash_types hash_type);
+
+const EVP_MD *
+lws_gencrypto_openssl_hash_to_EVP_MD(enum lws_genhash_types hash_type);
+
+#if !defined(LWS_HAVE_BN_bn2binpad)
+int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen);
+#endif
+++ /dev/null
-/*
- * 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
- *
- * gencrypto openssl-specific helper declarations
- */
-
-/*
- * one of these per different client context
- * cc_owner is in lws_context.lws_context_tls
- */
-
-struct lws_tls_client_reuse {
- lws_tls_ctx *ssl_client_ctx;
- uint8_t hash[32];
- struct lws_dll2 cc_list;
- int refcount;
- int index;
-};
-
-typedef int (*next_proto_cb)(SSL *, const unsigned char **out,
- unsigned char *outlen, const unsigned char *in,
- unsigned int inlen, void *arg);
-
-struct lws_x509_cert {
- X509 *cert; /* X509 is opaque, this has to be a pointer */
-};
-
-int
-lws_gencrypto_openssl_hash_to_NID(enum lws_genhash_types hash_type);
-
-const EVP_MD *
-lws_gencrypto_openssl_hash_to_EVP_MD(enum lws_genhash_types hash_type);
-
-#if !defined(LWS_HAVE_BN_bn2binpad)
-int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen);
-#endif
+++ /dev/null
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010-2018 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
- */
-
-#include "core/private.h"
-#include "tls/openssl/private.h"
-#include <errno.h>
-
-int openssl_websocket_private_data_index,
- openssl_SSL_CTX_private_data_index;
-
-/*
- * Care: many openssl apis return 1 for success. These are translated to the
- * lws convention of 0 for success.
- */
-
-int lws_openssl_describe_cipher(struct lws *wsi)
-{
-#if !defined(LWS_WITH_NO_LOGS)
- int np = -1;
- SSL *s = wsi->tls.ssl;
-
- SSL_get_cipher_bits(s, &np);
- lwsl_info("%s: wsi %p: %s, %s, %d bits, %s\n", __func__, wsi,
- SSL_get_cipher_name(s), SSL_get_cipher(s), np,
- SSL_get_cipher_version(s));
-#endif
-
- return 0;
-}
-
-int lws_ssl_get_error(struct lws *wsi, int n)
-{
- int m;
-
- if (!wsi->tls.ssl)
- return 99;
-
- m = SSL_get_error(wsi->tls.ssl, n);
- lwsl_debug("%s: %p %d -> %d (errno %d)\n", __func__, wsi->tls.ssl, n, m,
- errno);
-
- return m;
-}
-
-static int
-lws_context_init_ssl_pem_passwd_cb(char *buf, int size, int rwflag,
- void *userdata)
-{
- struct lws_context_creation_info * info =
- (struct lws_context_creation_info *)userdata;
-
- strncpy(buf, info->ssl_private_key_password, size);
- buf[size - 1] = '\0';
-
- return (int)strlen(buf);
-}
-
-static int
-lws_context_init_ssl_pem_passwd_client_cb(char *buf, int size, int rwflag,
- void *userdata)
-{
- struct lws_context_creation_info * info =
- (struct lws_context_creation_info *)userdata;
- const char *p = info->ssl_private_key_password;
-
- if (info->client_ssl_private_key_password)
- p = info->client_ssl_private_key_password;
-
- strncpy(buf, p, size);
- buf[size - 1] = '\0';
-
- return (int)strlen(buf);
-}
-
-void
-lws_ssl_bind_passphrase(SSL_CTX *ssl_ctx, int is_client,
- const struct lws_context_creation_info *info)
-{
- if (!info->ssl_private_key_password &&
- !info->client_ssl_private_key_password)
- return;
- /*
- * password provided, set ssl callback and user data
- * for checking password which will be trigered during
- * SSL_CTX_use_PrivateKey_file function
- */
- SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, (void *)info);
- SSL_CTX_set_default_passwd_cb(ssl_ctx, is_client ?
- lws_context_init_ssl_pem_passwd_client_cb:
- lws_context_init_ssl_pem_passwd_cb);
-}
-
-static void
-lws_ssl_destroy_client_ctx(struct lws_vhost *vhost)
-{
- struct lws_tls_client_reuse *tcr;
-
- if (vhost->tls.user_supplied_ssl_ctx || !vhost->tls.ssl_client_ctx)
- return;
-
- tcr = SSL_CTX_get_ex_data(vhost->tls.ssl_client_ctx,
- openssl_SSL_CTX_private_data_index);
-
- if (!tcr || --tcr->refcount)
- return;
-
- SSL_CTX_free(vhost->tls.ssl_client_ctx);
- vhost->tls.ssl_client_ctx = NULL;
-
- vhost->context->tls.count_client_contexts--;
-
- lws_dll2_remove(&tcr->cc_list);
- lws_free(tcr);
-}
-
-LWS_VISIBLE void
-lws_ssl_destroy(struct lws_vhost *vhost)
-{
- if (!lws_check_opt(vhost->context->options,
- LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT))
- return;
-
- if (vhost->tls.ssl_ctx)
- SSL_CTX_free(vhost->tls.ssl_ctx);
-
- lws_ssl_destroy_client_ctx(vhost);
-
-// after 1.1.0 no need
-#if (OPENSSL_VERSION_NUMBER < 0x10100000)
-// <= 1.0.1f = old api, 1.0.1g+ = new api
-#if (OPENSSL_VERSION_NUMBER <= 0x1000106f) || defined(USE_WOLFSSL)
- ERR_remove_state(0);
-#else
-#if OPENSSL_VERSION_NUMBER >= 0x1010005f && \
- !defined(LIBRESSL_VERSION_NUMBER) && \
- !defined(OPENSSL_IS_BORINGSSL)
- ERR_remove_thread_state();
-#else
- ERR_remove_thread_state(NULL);
-#endif
-#endif
- /* not needed after 1.1.0 */
-#if (OPENSSL_VERSION_NUMBER >= 0x10002000) && \
- (OPENSSL_VERSION_NUMBER <= 0x10100000)
- SSL_COMP_free_compression_methods();
-#endif
- ERR_free_strings();
- EVP_cleanup();
- CRYPTO_cleanup_all_ex_data();
-#endif
-}
-
-LWS_VISIBLE int
-lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len)
-{
- struct lws_context *context = wsi->context;
- struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
- int n = 0, m;
-
- if (!wsi->tls.ssl)
- return lws_ssl_capable_read_no_ssl(wsi, buf, len);
-
- lws_stats_bump(pt, LWSSTATS_C_API_READ, 1);
-
- errno = 0;
- ERR_clear_error();
- n = SSL_read(wsi->tls.ssl, buf, len);
-#if defined(LWS_WITH_ESP32)
- if (!n && errno == LWS_ENOTCONN) {
- lwsl_debug("%p: SSL_read ENOTCONN\n", wsi);
- return LWS_SSL_CAPABLE_ERROR;
- }
-#endif
-#if defined(LWS_WITH_STATS)
- if (!wsi->seen_rx && wsi->accept_start_us) {
- lws_stats_bump(pt, LWSSTATS_US_SSL_RX_DELAY_AVG,
- lws_now_usecs() -
- wsi->accept_start_us);
- lws_stats_bump(pt, LWSSTATS_C_SSL_CONNS_HAD_RX, 1);
- wsi->seen_rx = 1;
- }
-#endif
-
-
- lwsl_debug("%p: SSL_read says %d\n", wsi, n);
- /* manpage: returning 0 means connection shut down
- *
- * 2018-09-10: https://github.com/openssl/openssl/issues/1903
- *
- * So, in summary, if you get a 0 or -1 return from SSL_read() /
- * SSL_write(), you should call SSL_get_error():
- *
- * - If you get back SSL_ERROR_RETURN_ZERO then you know the connection
- * has been cleanly shutdown by the peer. To fully close the
- * connection you may choose to call SSL_shutdown() to send a
- * close_notify back.
- *
- * - If you get back SSL_ERROR_SSL then some kind of internal or
- * protocol error has occurred. More details will be on the SSL error
- * queue. You can also call SSL_get_shutdown(). If this indicates a
- * state of SSL_RECEIVED_SHUTDOWN then you know a fatal alert has
- * been received from the peer (if it had been a close_notify then
- * SSL_get_error() would have returned SSL_ERROR_RETURN_ZERO).
- * SSL_ERROR_SSL is considered fatal - you should not call
- * SSL_shutdown() in this case.
- *
- * - If you get back SSL_ERROR_SYSCALL then some kind of fatal (i.e.
- * non-retryable) error has occurred in a system call.
- */
- if (n <= 0) {
- m = lws_ssl_get_error(wsi, n);
- lwsl_debug("%p: ssl err %d errno %d\n", wsi, m, errno);
- if (m == SSL_ERROR_ZERO_RETURN) /* cleanly shut down */
- return LWS_SSL_CAPABLE_ERROR;
-
- /* hm not retryable.. could be 0 size pkt or error */
-
- if (m == SSL_ERROR_SSL || m == SSL_ERROR_SYSCALL ||
- errno == LWS_ENOTCONN) {
-
- /* unclean, eg closed conn */
-
- wsi->socket_is_permanently_unusable = 1;
-
- return LWS_SSL_CAPABLE_ERROR;
- }
-
- /* retryable? */
-
- if (SSL_want_read(wsi->tls.ssl)) {
- lwsl_debug("%s: WANT_READ\n", __func__);
- lwsl_debug("%p: LWS_SSL_CAPABLE_MORE_SERVICE\n", wsi);
- return LWS_SSL_CAPABLE_MORE_SERVICE;
- }
- if (SSL_want_write(wsi->tls.ssl)) {
- lwsl_debug("%s: WANT_WRITE\n", __func__);
- lwsl_debug("%p: LWS_SSL_CAPABLE_MORE_SERVICE\n", wsi);
- return LWS_SSL_CAPABLE_MORE_SERVICE;
- }
-
- /* keep on trucking it seems */
- }
-
- lws_stats_bump(pt, LWSSTATS_B_READ, n);
-
- if (wsi->vhost)
- wsi->vhost->conn_stats.rx += n;
-
- // lwsl_hexdump_err(buf, n);
-
- /*
- * if it was our buffer that limited what we read,
- * check if SSL has additional data pending inside SSL buffers.
- *
- * Because these won't signal at the network layer with POLLIN
- * and if we don't realize, this data will sit there forever
- */
- if (n != len)
- goto bail;
- if (!wsi->tls.ssl)
- goto bail;
-
- if (SSL_pending(wsi->tls.ssl) &&
- lws_dll2_is_detached(&wsi->tls.dll_pending_tls))
- lws_dll2_add_head(&wsi->tls.dll_pending_tls,
- &pt->tls.dll_pending_tls_owner);
-
- return n;
-bail:
- lws_ssl_remove_wsi_from_buffered_list(wsi);
-
- return n;
-}
-
-LWS_VISIBLE int
-lws_ssl_pending(struct lws *wsi)
-{
- if (!wsi->tls.ssl)
- return 0;
-
- return SSL_pending(wsi->tls.ssl);
-}
-
-LWS_VISIBLE int
-lws_ssl_capable_write(struct lws *wsi, unsigned char *buf, int len)
-{
- int n, m;
-
- if (!wsi->tls.ssl)
- return lws_ssl_capable_write_no_ssl(wsi, buf, len);
-
- errno = 0;
- ERR_clear_error();
- n = SSL_write(wsi->tls.ssl, buf, len);
- if (n > 0)
- return n;
-
- m = lws_ssl_get_error(wsi, n);
- if (m != SSL_ERROR_SYSCALL) {
- if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) {
- lwsl_notice("%s: want read\n", __func__);
-
- return LWS_SSL_CAPABLE_MORE_SERVICE;
- }
-
- if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) {
- lws_set_blocking_send(wsi);
-
- lwsl_debug("%s: want write\n", __func__);
-
- return LWS_SSL_CAPABLE_MORE_SERVICE;
- }
- }
-
- lwsl_debug("%s failed: %s\n",__func__, ERR_error_string(m, NULL));
- lws_tls_err_describe_clear();
-
- wsi->socket_is_permanently_unusable = 1;
-
- return LWS_SSL_CAPABLE_ERROR;
-}
-
-void
-lws_ssl_info_callback(const SSL *ssl, int where, int ret)
-{
- struct lws *wsi;
- struct lws_context *context;
- struct lws_ssl_info si;
-
-#ifndef USE_WOLFSSL
- context = (struct lws_context *)SSL_CTX_get_ex_data(
- SSL_get_SSL_CTX(ssl),
- openssl_SSL_CTX_private_data_index);
-#else
- context = (struct lws_context *)SSL_CTX_get_ex_data(
- SSL_get_SSL_CTX((SSL*) ssl),
- openssl_SSL_CTX_private_data_index);
-#endif
- if (!context)
- return;
- wsi = wsi_from_fd(context, SSL_get_fd(ssl));
- if (!wsi)
- return;
-
- if (!(where & wsi->vhost->tls.ssl_info_event_mask))
- return;
-
- si.where = where;
- si.ret = ret;
-
- if (user_callback_handle_rxflow(wsi->protocol->callback,
- wsi, LWS_CALLBACK_SSL_INFO,
- wsi->user_space, &si, 0))
- lws_set_timeout(wsi, PENDING_TIMEOUT_KILLED_BY_SSL_INFO, -1);
-}
-
-
-LWS_VISIBLE int
-lws_ssl_close(struct lws *wsi)
-{
- lws_sockfd_type n;
-
- if (!wsi->tls.ssl)
- return 0; /* not handled */
-
-#if defined (LWS_HAVE_SSL_SET_INFO_CALLBACK)
- /* kill ssl callbacks, because we will remove the fd from the
- * table linking it to the wsi
- */
- if (wsi->vhost->tls.ssl_info_event_mask)
- SSL_set_info_callback(wsi->tls.ssl, NULL);
-#endif
-
- n = SSL_get_fd(wsi->tls.ssl);
- if (!wsi->socket_is_permanently_unusable)
- SSL_shutdown(wsi->tls.ssl);
- compatible_close(n);
- SSL_free(wsi->tls.ssl);
- wsi->tls.ssl = NULL;
-
- if (wsi->context->simultaneous_ssl_restriction &&
- wsi->context->simultaneous_ssl-- ==
- wsi->context->simultaneous_ssl_restriction)
- /* we made space and can do an accept */
- lws_gate_accepts(wsi->context, 1);
-
- // lwsl_notice("%s: ssl restr %d, simul %d\n", __func__,
- // wsi->context->simultaneous_ssl_restriction,
- // wsi->context->simultaneous_ssl);
-
-#if defined(LWS_WITH_STATS)
- wsi->context->updated = 1;
-#endif
-
- return 1; /* handled */
-}
-
-void
-lws_ssl_SSL_CTX_destroy(struct lws_vhost *vhost)
-{
- if (vhost->tls.ssl_ctx)
- SSL_CTX_free(vhost->tls.ssl_ctx);
-
- lws_ssl_destroy_client_ctx(vhost);
-
-#if defined(LWS_WITH_ACME)
- lws_tls_acme_sni_cert_destroy(vhost);
-#endif
-}
-
-void
-lws_ssl_context_destroy(struct lws_context *context)
-{
-// after 1.1.0 no need
-#if (OPENSSL_VERSION_NUMBER < 0x10100000)
-// <= 1.0.1f = old api, 1.0.1g+ = new api
-#if (OPENSSL_VERSION_NUMBER <= 0x1000106f) || defined(USE_WOLFSSL)
- ERR_remove_state(0);
-#else
-#if OPENSSL_VERSION_NUMBER >= 0x1010005f && \
- !defined(LIBRESSL_VERSION_NUMBER) && \
- !defined(OPENSSL_IS_BORINGSSL)
- ERR_remove_thread_state();
-#else
- ERR_remove_thread_state(NULL);
-#endif
-#endif
- // after 1.1.0 no need
-#if (OPENSSL_VERSION_NUMBER >= 0x10002000) && (OPENSSL_VERSION_NUMBER <= 0x10100000)
- SSL_COMP_free_compression_methods();
-#endif
- ERR_free_strings();
- EVP_cleanup();
- CRYPTO_cleanup_all_ex_data();
-#endif
-}
-
-lws_tls_ctx *
-lws_tls_ctx_from_wsi(struct lws *wsi)
-{
- if (!wsi->tls.ssl)
- return NULL;
-
- return SSL_get_SSL_CTX(wsi->tls.ssl);
-}
-
-enum lws_ssl_capable_status
-__lws_tls_shutdown(struct lws *wsi)
-{
- int n;
-
- errno = 0;
- ERR_clear_error();
- n = SSL_shutdown(wsi->tls.ssl);
- lwsl_debug("SSL_shutdown=%d for fd %d\n", n, wsi->desc.sockfd);
- switch (n) {
- case 1: /* successful completion */
- n = shutdown(wsi->desc.sockfd, SHUT_WR);
- return LWS_SSL_CAPABLE_DONE;
-
- case 0: /* needs a retry */
- __lws_change_pollfd(wsi, 0, LWS_POLLIN);
- return LWS_SSL_CAPABLE_MORE_SERVICE;
-
- default: /* fatal error, or WANT */
- n = SSL_get_error(wsi->tls.ssl, n);
- if (n != SSL_ERROR_SYSCALL && n != SSL_ERROR_SSL) {
- if (SSL_want_read(wsi->tls.ssl)) {
- lwsl_debug("(wants read)\n");
- __lws_change_pollfd(wsi, 0, LWS_POLLIN);
- return LWS_SSL_CAPABLE_MORE_SERVICE_READ;
- }
- if (SSL_want_write(wsi->tls.ssl)) {
- lwsl_debug("(wants write)\n");
- __lws_change_pollfd(wsi, 0, LWS_POLLOUT);
- return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE;
- }
- }
- return LWS_SSL_CAPABLE_ERROR;
- }
-}
-
-
-static int
-tops_fake_POLLIN_for_buffered_openssl(struct lws_context_per_thread *pt)
-{
- return lws_tls_fake_POLLIN_for_buffered(pt);
-}
-
-const struct lws_tls_ops tls_ops_openssl = {
- /* fake_POLLIN_for_buffered */ tops_fake_POLLIN_for_buffered_openssl,
-};
+++ /dev/null
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010-2018 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
- */
-
-#include "core/private.h"
-#include "tls/openssl/private.h"
-
-extern int openssl_websocket_private_data_index,
-openssl_SSL_CTX_private_data_index;
-
-char* lws_ssl_get_error_string(int status, int ret, char *buf, size_t len) {
- switch (status) {
- case SSL_ERROR_NONE:
- return lws_strncpy(buf, "SSL_ERROR_NONE", len);
- case SSL_ERROR_ZERO_RETURN:
- return lws_strncpy(buf, "SSL_ERROR_ZERO_RETURN", len);
- case SSL_ERROR_WANT_READ:
- return lws_strncpy(buf, "SSL_ERROR_WANT_READ", len);
- case SSL_ERROR_WANT_WRITE:
- return lws_strncpy(buf, "SSL_ERROR_WANT_WRITE", len);
- case SSL_ERROR_WANT_CONNECT:
- return lws_strncpy(buf, "SSL_ERROR_WANT_CONNECT", len);
- case SSL_ERROR_WANT_ACCEPT:
- return lws_strncpy(buf, "SSL_ERROR_WANT_ACCEPT", len);
- case SSL_ERROR_WANT_X509_LOOKUP:
- return lws_strncpy(buf, "SSL_ERROR_WANT_X509_LOOKUP", len);
- case SSL_ERROR_SYSCALL:
- switch (ret) {
- case 0:
- lws_snprintf(buf, len, "SSL_ERROR_SYSCALL: EOF");
- return buf;
- case -1:
-#ifndef LWS_PLAT_OPTEE
- lws_snprintf(buf, len, "SSL_ERROR_SYSCALL: %s",
- strerror(errno));
-#else
- lws_snprintf(buf, len, "SSL_ERROR_SYSCALL: %d", errno);
-#endif
- return buf;
- default:
- return strncpy(buf, "SSL_ERROR_SYSCALL", len);
- }
- case SSL_ERROR_SSL:
- return "SSL_ERROR_SSL";
- default:
- return "SSL_ERROR_UNKNOWN";
- }
-}
-
-void
-lws_tls_err_describe_clear(void)
-{
- char buf[160];
- unsigned long l;
-
- do {
- l = ERR_get_error();
- if (!l)
- break;
-
- ERR_error_string_n(l, buf, sizeof(buf));
- lwsl_info(" openssl error: %s\n", buf);
- } while (l);
- lwsl_info("\n");
-}
-
-#if LWS_MAX_SMP != 1
-
-static pthread_mutex_t *openssl_mutexes;
-
-static void
-lws_openssl_lock_callback(int mode, int type, const char *file, int line)
-{
- (void)file;
- (void)line;
-
- if (mode & CRYPTO_LOCK)
- pthread_mutex_lock(&openssl_mutexes[type]);
- else
- pthread_mutex_unlock(&openssl_mutexes[type]);
-}
-
-static unsigned long
-lws_openssl_thread_id(void)
-{
- return (unsigned long)pthread_self();
-}
-#endif
-
-
-int
-lws_context_init_ssl_library(const struct lws_context_creation_info *info)
-{
-#ifdef USE_WOLFSSL
-#ifdef USE_OLD_CYASSL
- lwsl_info(" Compiled with CyaSSL support\n");
-#else
- lwsl_info(" Compiled with wolfSSL support\n");
-#endif
-#else
-#if defined(LWS_WITH_BORINGSSL)
- lwsl_info(" Compiled with BoringSSL support\n");
-#else
- lwsl_info(" Compiled with OpenSSL support\n");
-#endif
-#endif
- if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT)) {
- lwsl_info(" SSL disabled: no "
- "LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT\n");
- return 0;
- }
-
- /* basic openssl init */
-
- lwsl_info("Doing SSL library init\n");
-
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
- SSL_library_init();
- OpenSSL_add_all_algorithms();
- SSL_load_error_strings();
-#else
- OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
-#endif
-#if defined(LWS_WITH_NETWORK)
- openssl_websocket_private_data_index =
- SSL_get_ex_new_index(0, "lws", NULL, NULL, NULL);
-
- openssl_SSL_CTX_private_data_index = SSL_CTX_get_ex_new_index(0,
- NULL, NULL, NULL, NULL);
-#endif
-
-#if LWS_MAX_SMP != 1
- {
- int n;
-
- openssl_mutexes = (pthread_mutex_t *)
- OPENSSL_malloc(CRYPTO_num_locks() *
- sizeof(openssl_mutexes[0]));
-
- for (n = 0; n < CRYPTO_num_locks(); n++)
- pthread_mutex_init(&openssl_mutexes[n], NULL);
-
- /*
- * These "functions" disappeared in later OpenSSL which is
- * already threadsafe.
- */
-
- (void)lws_openssl_thread_id;
- (void)lws_openssl_lock_callback;
-
- CRYPTO_set_id_callback(lws_openssl_thread_id);
- CRYPTO_set_locking_callback(lws_openssl_lock_callback);
- }
-#endif
-
- return 0;
-}
-
-void
-lws_context_deinit_ssl_library(struct lws_context *context)
-{
-#if LWS_MAX_SMP != 1
- int n;
-
- if (!lws_check_opt(context->options,
- LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT))
- return;
-
- CRYPTO_set_locking_callback(NULL);
-
- for (n = 0; n < CRYPTO_num_locks(); n++)
- pthread_mutex_destroy(&openssl_mutexes[n]);
-
- OPENSSL_free(openssl_mutexes);
-#endif
-}
+++ /dev/null
-/*
- * libwebsockets - OpenSSL-specific lws apis
- *
- * 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
- */
-
-#include "core/private.h"
-#include "tls/openssl/private.h"
-
-#if !defined(LWS_PLAT_OPTEE)
-static int
-dec(char c)
-{
- return c - '0';
-}
-#endif
-
-static time_t
-lws_tls_openssl_asn1time_to_unix(ASN1_TIME *as)
-{
-#if !defined(LWS_PLAT_OPTEE)
-
- const char *p = (const char *)as->data;
- struct tm t;
-
- /* [YY]YYMMDDHHMMSSZ */
-
- memset(&t, 0, sizeof(t));
-
- if (strlen(p) == 13) {
- t.tm_year = (dec(p[0]) * 10) + dec(p[1]) + 100;
- p += 2;
- } else {
- t.tm_year = (dec(p[0]) * 1000) + (dec(p[1]) * 100) +
- (dec(p[2]) * 10) + dec(p[3]);
- p += 4;
- }
- t.tm_mon = (dec(p[0]) * 10) + dec(p[1]) - 1;
- p += 2;
- t.tm_mday = (dec(p[0]) * 10) + dec(p[1]) - 1;
- p += 2;
- t.tm_hour = (dec(p[0]) * 10) + dec(p[1]);
- p += 2;
- t.tm_min = (dec(p[0]) * 10) + dec(p[1]);
- p += 2;
- t.tm_sec = (dec(p[0]) * 10) + dec(p[1]);
- t.tm_isdst = 0;
-
- return mktime(&t);
-#else
- return (time_t)-1;
-#endif
-}
-
-int
-lws_tls_openssl_cert_info(X509 *x509, enum lws_tls_cert_info type,
- union lws_tls_cert_info_results *buf, size_t len)
-{
- X509_NAME *xn;
-#if !defined(LWS_PLAT_OPTEE)
- char *p;
-#endif
-
- if (!x509)
- return -1;
-
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(X509_get_notBefore)
-#define X509_get_notBefore(x) X509_getm_notBefore(x)
-#define X509_get_notAfter(x) X509_getm_notAfter(x)
-#endif
-
- switch (type) {
- case LWS_TLS_CERT_INFO_VALIDITY_FROM:
- buf->time = lws_tls_openssl_asn1time_to_unix(
- X509_get_notBefore(x509));
- if (buf->time == (time_t)-1)
- return -1;
- break;
-
- case LWS_TLS_CERT_INFO_VALIDITY_TO:
- buf->time = lws_tls_openssl_asn1time_to_unix(
- X509_get_notAfter(x509));
- if (buf->time == (time_t)-1)
- return -1;
- break;
-
- case LWS_TLS_CERT_INFO_COMMON_NAME:
-#if defined(LWS_PLAT_OPTEE)
- return -1;
-#else
- xn = X509_get_subject_name(x509);
- if (!xn)
- return -1;
- X509_NAME_oneline(xn, buf->ns.name, (int)len - 2);
- p = strstr(buf->ns.name, "/CN=");
- if (p)
- memmove(buf->ns.name, p + 4, strlen(p + 4) + 1);
- buf->ns.len = (int)strlen(buf->ns.name);
- return 0;
-#endif
- case LWS_TLS_CERT_INFO_ISSUER_NAME:
- xn = X509_get_issuer_name(x509);
- if (!xn)
- return -1;
- X509_NAME_oneline(xn, buf->ns.name, (int)len - 1);
- buf->ns.len = (int)strlen(buf->ns.name);
- return 0;
-
- case LWS_TLS_CERT_INFO_USAGE:
-#if defined(LWS_HAVE_X509_get_key_usage)
- buf->usage = X509_get_key_usage(x509);
- break;
-#else
- return -1;
-#endif
-
- case LWS_TLS_CERT_INFO_OPAQUE_PUBLIC_KEY:
- {
-#ifndef USE_WOLFSSL
- size_t klen = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x509), NULL);
- uint8_t *tmp, *ptmp;
-
- if (!klen || klen > len)
- return -1;
-
- tmp = (uint8_t *)OPENSSL_malloc(klen);
- if (!tmp)
- return -1;
-
- ptmp = tmp;
- if (i2d_X509_PUBKEY(
- X509_get_X509_PUBKEY(x509), &ptmp) != (int)klen ||
- !ptmp || lws_ptr_diff(ptmp, tmp) != (int)klen) {
- lwsl_info("%s: cert public key extraction failed\n",
- __func__);
- if (ptmp)
- OPENSSL_free(tmp);
-
- return -1;
- }
-
- buf->ns.len = (int)klen;
- memcpy(buf->ns.name, tmp, klen);
- OPENSSL_free(tmp);
-#endif
- return 0;
- }
- default:
- return -1;
- }
-
- return 0;
-}
-
-int
-lws_x509_info(struct lws_x509_cert *x509, enum lws_tls_cert_info type,
- union lws_tls_cert_info_results *buf, size_t len)
-{
- return lws_tls_openssl_cert_info(x509->cert, type, buf, len);
-}
-
-#if defined(LWS_WITH_NETWORK)
-int
-lws_tls_vhost_cert_info(struct lws_vhost *vhost, enum lws_tls_cert_info type,
- union lws_tls_cert_info_results *buf, size_t len)
-{
-#if defined(LWS_HAVE_SSL_CTX_get0_certificate)
- X509 *x509 = SSL_CTX_get0_certificate(vhost->tls.ssl_ctx);
-
- return lws_tls_openssl_cert_info(x509, type, buf, len);
-#else
- lwsl_notice("openssl is too old to support %s\n", __func__);
-
- return -1;
-#endif
-}
-
-
-
-int
-lws_tls_peer_cert_info(struct lws *wsi, enum lws_tls_cert_info type,
- union lws_tls_cert_info_results *buf, size_t len)
-{
- int rc = 0;
- X509 *x509;
-
- wsi = lws_get_network_wsi(wsi);
-
- x509 = SSL_get_peer_certificate(wsi->tls.ssl);
-
- if (!x509) {
- lwsl_debug("no peer cert\n");
-
- return -1;
- }
-
- switch (type) {
- case LWS_TLS_CERT_INFO_VERIFIED:
- buf->verified = SSL_get_verify_result(wsi->tls.ssl) ==
- X509_V_OK;
- break;
- default:
- rc = lws_tls_openssl_cert_info(x509, type, buf, len);
- }
-
- X509_free(x509);
-
- return rc;
-}
-#endif
-
-int
-lws_x509_create(struct lws_x509_cert **x509)
-{
- *x509 = lws_malloc(sizeof(**x509), __func__);
- if (*x509)
- (*x509)->cert = NULL;
-
- return !(*x509);
-}
-
-int
-lws_x509_parse_from_pem(struct lws_x509_cert *x509, const void *pem, size_t len)
-{
- BIO* bio = BIO_new(BIO_s_mem());
-
- BIO_write(bio, pem, len);
- x509->cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
- BIO_free(bio);
- if (!x509->cert) {
- lwsl_err("%s: unable to parse PEM cert\n", __func__);
- lws_tls_err_describe_clear();
-
- return -1;
- }
-
- return 0;
-}
-
-int
-lws_x509_verify(struct lws_x509_cert *x509, struct lws_x509_cert *trusted,
- const char *common_name)
-{
- char c[32], *p;
- int ret;
-
- if (common_name) {
- X509_NAME *xn = X509_get_subject_name(x509->cert);
- if (!xn)
- return -1;
- X509_NAME_oneline(xn, c, (int)sizeof(c) - 2);
- p = strstr(c, "/CN=");
- if (p)
- p = p + 4;
- else
- p = c;
-
- if (strcmp(p, common_name)) {
- lwsl_err("%s: common name mismatch\n", __func__);
- return -1;
- }
- }
-
- ret = X509_check_issued(trusted->cert, x509->cert);
- if (ret != X509_V_OK) {
- lwsl_err("%s: unable to verify cert relationship\n", __func__);
- lws_tls_err_describe_clear();
-
- return -1;
- }
-
- return 0;
-}
-
-#if defined(LWS_WITH_JOSE)
-int
-lws_x509_public_to_jwk(struct lws_jwk *jwk, struct lws_x509_cert *x509,
- const char *curves, int rsa_min_bits)
-{
- int id, n, ret = -1, count;
- ASN1_OBJECT *obj = NULL;
- const EC_POINT *ecpoint;
- const EC_GROUP *ecgroup;
- EC_KEY *ecpub = NULL;
- X509_PUBKEY *pubkey;
- RSA *rsapub = NULL;
- BIGNUM *mpi[4];
- EVP_PKEY *pkey;
-
- memset(jwk, 0, sizeof(*jwk));
-
- pubkey = X509_get_X509_PUBKEY(x509->cert);
- if (!pubkey) {
- lwsl_err("%s: missing pubkey alg in cert\n", __func__);
-
- goto bail;
- }
-
- if (X509_PUBKEY_get0_param(&obj, NULL, NULL, NULL, pubkey) != 1) {
- lwsl_err("%s: missing pubkey alg in cert\n", __func__);
-
- goto bail;
- }
-
- id = OBJ_obj2nid(obj);
- if (id == NID_undef) {
- lwsl_err("%s: missing pubkey alg in cert\n", __func__);
-
- goto bail;
- }
-
- lwsl_debug("%s: key type %d \"%s\"\n", __func__, id, OBJ_nid2ln(id));
-
- pkey = X509_get_pubkey(x509->cert);
- if (!pkey) {
- lwsl_notice("%s: unable to extract pubkey", __func__);
-
- goto bail;
- }
-
- switch (id) {
- case NID_X9_62_id_ecPublicKey:
- lwsl_debug("%s: EC key\n", __func__);
- jwk->kty = LWS_GENCRYPTO_KTY_EC;
-
- if (!curves) {
- lwsl_err("%s: ec curves not allowed\n", __func__);
-
- goto bail1;
- }
-
- ecpub = EVP_PKEY_get1_EC_KEY(pkey);
- if (!ecpub) {
- lwsl_notice("%s: missing EC pubkey\n", __func__);
-
- goto bail1;
- }
-
- ecpoint = EC_KEY_get0_public_key(ecpub);
- if (!ecpoint) {
- lwsl_err("%s: EC_KEY_get0_public_key failed\n", __func__);
- goto bail2;
- }
-
- ecgroup = EC_KEY_get0_group(ecpub);
- if (!ecgroup) {
- lwsl_err("%s: EC_KEY_get0_group failed\n", __func__);
- goto bail2;
- }
-
- /* validate the curve against ones we allow */
-
- if (lws_genec_confirm_curve_allowed_by_tls_id(curves,
- EC_GROUP_get_curve_name(ecgroup), jwk))
- /* already logged */
- goto bail2;
-
- mpi[LWS_GENCRYPTO_EC_KEYEL_CRV] = NULL;
- mpi[LWS_GENCRYPTO_EC_KEYEL_X] = BN_new(); /* X */
- mpi[LWS_GENCRYPTO_EC_KEYEL_D] = NULL;
- mpi[LWS_GENCRYPTO_EC_KEYEL_Y] = BN_new(); /* Y */
-
-#if defined(LWS_HAVE_EC_POINT_get_affine_coordinates)
- if (EC_POINT_get_affine_coordinates(ecgroup, ecpoint,
-#else
- if (EC_POINT_get_affine_coordinates_GFp(ecgroup, ecpoint,
-#endif
- mpi[LWS_GENCRYPTO_EC_KEYEL_X],
- mpi[LWS_GENCRYPTO_EC_KEYEL_Y],
- NULL) != 1) {
- BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]);
- BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]);
- lwsl_err("%s: EC_POINT_get_aff failed\n", __func__);
- goto bail2;
- }
- count = LWS_GENCRYPTO_EC_KEYEL_COUNT;
- n = LWS_GENCRYPTO_EC_KEYEL_X;
- break;
-
- case NID_rsaEncryption:
- lwsl_debug("%s: rsa key\n", __func__);
- jwk->kty = LWS_GENCRYPTO_KTY_RSA;
-
- rsapub = EVP_PKEY_get1_RSA(pkey);
- if (!rsapub) {
- lwsl_notice("%s: missing RSA pubkey\n", __func__);
-
- goto bail1;
- }
-
- if ((size_t)RSA_size(rsapub) * 8 < (size_t)rsa_min_bits) {
- lwsl_err("%s: key bits %d less than minimum %d\n",
- __func__, RSA_size(rsapub) * 8, rsa_min_bits);
-
- goto bail2;
- }
-
-#if defined(LWS_HAVE_RSA_SET0_KEY)
- /* we don't need d... but the api wants to write it */
- RSA_get0_key(rsapub,
- (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_N],
- (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_E],
- (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_D]);
-#else
- mpi[LWS_GENCRYPTO_RSA_KEYEL_E] = rsapub->e;
- mpi[LWS_GENCRYPTO_RSA_KEYEL_N] = rsapub->n;
- mpi[LWS_GENCRYPTO_RSA_KEYEL_D] = NULL;
-#endif
- count = LWS_GENCRYPTO_RSA_KEYEL_D;
- n = LWS_GENCRYPTO_RSA_KEYEL_E;
- break;
- default:
- lwsl_err("%s: unknown NID\n", __func__);
- goto bail2;
- }
-
- for (; n < count; n++) {
- if (!mpi[n])
- continue;
- jwk->e[n].len = BN_num_bytes(mpi[n]);
- jwk->e[n].buf = lws_malloc(jwk->e[n].len, "certkeyimp");
- if (!jwk->e[n].buf) {
- if (id == NID_X9_62_id_ecPublicKey) {
- BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]);
- BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]);
- }
- goto bail2;
- }
- BN_bn2bin(mpi[n], jwk->e[n].buf);
- }
-
- if (id == NID_X9_62_id_ecPublicKey) {
- BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]);
- BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]);
- }
-
- ret = 0;
-
-bail2:
- if (id == NID_X9_62_id_ecPublicKey)
- EC_KEY_free(ecpub);
- else
- RSA_free(rsapub);
-
-bail1:
- EVP_PKEY_free(pkey);
-bail:
- /* jwk destroy will clean any partial state */
- if (ret)
- lws_jwk_destroy(jwk);
-
- return ret;
-}
-
-static int
-lws_x509_jwk_privkey_pem_pp_cb(char *buf, int size, int rwflag, void *u)
-{
- const char *pp = (const char *)u;
- int n = strlen(pp);
-
- if (n > size - 1)
- return -1;
-
- memcpy(buf, pp, n + 1);
-
- return n;
-}
-
-int
-lws_x509_jwk_privkey_pem(struct lws_jwk *jwk, void *pem, size_t len,
- const char *passphrase)
-{
- BIO* bio = BIO_new(BIO_s_mem());
- BIGNUM *mpi, *dummy[6];
- EVP_PKEY *pkey = NULL;
- EC_KEY *ecpriv = NULL;
- RSA *rsapriv = NULL;
- const BIGNUM *cmpi;
- int n, m, ret = -1;
-
- BIO_write(bio, pem, len);
- PEM_read_bio_PrivateKey(bio, &pkey, lws_x509_jwk_privkey_pem_pp_cb,
- (void *)passphrase);
- BIO_free(bio);
- lws_explicit_bzero((void *)pem, len);
- if (!pkey) {
- lwsl_err("%s: unable to parse PEM privkey\n", __func__);
- lws_tls_err_describe_clear();
-
- return -1;
- }
-
- /* confirm the key type matches the existing jwk situation */
-
- switch (jwk->kty) {
- case LWS_GENCRYPTO_KTY_EC:
- if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_EC) {
- lwsl_err("%s: jwk is EC but privkey isn't\n", __func__);
-
- goto bail;
- }
- ecpriv = EVP_PKEY_get1_EC_KEY(pkey);
- if (!ecpriv) {
- lwsl_notice("%s: missing EC key\n", __func__);
-
- goto bail;
- }
-
- cmpi = EC_KEY_get0_private_key(ecpriv);
-
- /* quick size check first */
-
- n = BN_num_bytes(cmpi);
- if (jwk->e[LWS_GENCRYPTO_EC_KEYEL_Y].len != (uint32_t)n) {
- lwsl_err("%s: jwk key size doesn't match\n", __func__);
-
- goto bail1;
- }
-
- /* TODO.. check public curve / group + point */
-
- jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].len = n;
- jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf = lws_malloc(n, "ec");
- if (!jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf)
- goto bail1;
-
- m = BN_bn2binpad(cmpi, jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf,
- jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].len);
- if ((unsigned int)m != (unsigned int)BN_num_bytes(cmpi))
- goto bail1;
-
- break;
-
- case LWS_GENCRYPTO_KTY_RSA:
- if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_RSA) {
- lwsl_err("%s: RSA jwk, non-RSA privkey\n", __func__);
-
- goto bail;
- }
- rsapriv = EVP_PKEY_get1_RSA(pkey);
- if (!rsapriv) {
- lwsl_notice("%s: missing RSA key\n", __func__);
-
- goto bail;
- }
-
-#if defined(LWS_HAVE_RSA_SET0_KEY)
- RSA_get0_key(rsapriv, (const BIGNUM **)&dummy[0], /* n */
- (const BIGNUM **)&dummy[1], /* e */
- (const BIGNUM **)&mpi); /* d */
- RSA_get0_factors(rsapriv, (const BIGNUM **)&dummy[4], /* p */
- (const BIGNUM **)&dummy[5]); /* q */
-#else
- dummy[0] = rsapriv->n;
- dummy[1] = rsapriv->e;
- dummy[4] = rsapriv->p;
- dummy[5] = rsapriv->q;
- mpi = rsapriv->d;
-#endif
-
- /* quick size check first */
-
- n = BN_num_bytes(mpi);
- if (jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].len != (uint32_t)n) {
- lwsl_err("%s: jwk key size doesn't match\n", __func__);
-
- goto bail1;
- }
-
- /* then check that n & e match what we got from the cert */
-
- dummy[2] = BN_bin2bn(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].buf,
- jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].len,
- NULL);
- dummy[3] = BN_bin2bn(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_E].buf,
- jwk->e[LWS_GENCRYPTO_RSA_KEYEL_E].len,
- NULL);
-
- m = BN_cmp(dummy[2], dummy[0]) | BN_cmp(dummy[3], dummy[1]);
- BN_clear_free(dummy[2]);
- BN_clear_free(dummy[3]);
- if (m) {
- lwsl_err("%s: privkey doesn't match jwk pubkey\n",
- __func__);
-
- goto bail1;
- }
-
- /* accept d from the PEM privkey into the JWK */
-
- jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].len = n;
- jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf = lws_malloc(n, "privjk");
- if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf)
- goto bail1;
-
- BN_bn2bin(mpi, jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf);
-
- /* accept p and q from the PEM privkey into the JWK */
-
- jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].len = BN_num_bytes(dummy[4]);
- jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf = lws_malloc(n, "privjk");
- if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf) {
- lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf);
- goto bail1;
- }
- BN_bn2bin(dummy[4], jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf);
-
- jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].len = BN_num_bytes(dummy[5]);
- jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf = lws_malloc(n, "privjk");
- if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf) {
- lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf);
- lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf);
- goto bail1;
- }
- BN_bn2bin(dummy[5], jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf);
- break;
- default:
- lwsl_err("%s: JWK has unknown kty %d\n", __func__, jwk->kty);
- return -1;
- }
-
- ret = 0;
-
-bail1:
- if (jwk->kty == LWS_GENCRYPTO_KTY_EC)
- EC_KEY_free(ecpriv);
- else
- RSA_free(rsapriv);
-
-bail:
- EVP_PKEY_free(pkey);
-
- return ret;
-}
-#endif
-
-void
-lws_x509_destroy(struct lws_x509_cert **x509)
-{
- if (!*x509)
- return;
-
- if ((*x509)->cert) {
- X509_free((*x509)->cert);
- (*x509)->cert = NULL;
- }
-
- lws_free_set_NULL(*x509);
-}
--- /dev/null
+/*
+ * 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
+ *
+ * This is included from private-lib-core.h if LWS_WITH_TLS
+ */
+
+#if !defined(__LWS_TLS_PRIVATE_H__)
+#define __LWS_TLS_PRIVATE_H__
+
+
+#if defined(LWS_WITH_TLS)
+
+#if defined(USE_WOLFSSL)
+ #if defined(USE_OLD_CYASSL)
+ #if defined(_WIN32)
+ #include <IDE/WIN/user_settings.h>
+ #include <cyassl/ctaocrypt/settings.h>
+ #else
+ #include <cyassl/options.h>
+ #endif
+ #include <cyassl/openssl/ssl.h>
+ #include <cyassl/error-ssl.h>
+ #else
+ #if defined(_WIN32)
+ #include <IDE/WIN/user_settings.h>
+ #include <wolfssl/wolfcrypt/settings.h>
+ #else
+ #include <wolfssl/options.h>
+ #endif
+ #include <wolfssl/openssl/ssl.h>
+ #include <wolfssl/error-ssl.h>
+ #define OPENSSL_NO_TLSEXT
+ #endif /* not USE_OLD_CYASSL */
+#else /* WOLFSSL */
+ #if defined(LWS_WITH_ESP32)
+ #define OPENSSL_NO_TLSEXT
+ #if !defined(LWS_AMAZON_RTOS)
+ /* AMAZON RTOS has its own setting via MTK_MBEDTLS_CONFIG_FILE */
+ #undef MBEDTLS_CONFIG_FILE
+ #define MBEDTLS_CONFIG_FILE <mbedtls/esp_config.h>
+ #endif
+ #include <mbedtls/ssl.h>
+ #include <mbedtls/aes.h>
+ #include <mbedtls/gcm.h>
+ #include <mbedtls/x509_crt.h>
+ #include "openssl/ssl.h" /* wrapper !!!! */
+ #else /* not esp32 */
+ #if defined(LWS_WITH_MBEDTLS)
+ #include <mbedtls/ssl.h>
+ #include <mbedtls/aes.h>
+ #include <mbedtls/gcm.h>
+ #include <mbedtls/x509_crt.h>
+ #include <mbedtls/x509_csr.h>
+ #include <mbedtls/ecp.h>
+ #include <mbedtls/ecdsa.h>
+ #include "openssl/ssl.h" /* wrapper !!!! */
+ #else
+ #include <openssl/ssl.h>
+ #include <openssl/evp.h>
+ #include <openssl/err.h>
+ #include <openssl/md5.h>
+ #include <openssl/sha.h>
+ #include <openssl/rsa.h>
+ #include <openssl/bn.h>
+ #include <openssl/aes.h>
+ #ifdef LWS_HAVE_OPENSSL_ECDH_H
+ #include <openssl/ecdh.h>
+ #endif
+ #if !defined(LWS_HAVE_EVP_MD_CTX_free)
+ #define EVP_MD_CTX_free EVP_MD_CTX_destroy
+ #endif
+ #include <openssl/x509v3.h>
+ #endif /* not mbedtls */
+ #if defined(OPENSSL_VERSION_NUMBER)
+ #if (OPENSSL_VERSION_NUMBER < 0x0009080afL)
+/*
+ * later openssl defines this to negate the presence of tlsext... but it was
+ * only introduced at 0.9.8j. Earlier versions don't know it exists so don't
+ * define it... making it look like the feature exists...
+ */
+ #define OPENSSL_NO_TLSEXT
+ #endif
+ #endif
+ #endif /* not ESP32 */
+#endif /* not USE_WOLFSSL */
+
+#endif /* LWS_WITH_TLS */
+
+enum lws_tls_extant {
+ LWS_TLS_EXTANT_NO,
+ LWS_TLS_EXTANT_YES,
+ LWS_TLS_EXTANT_ALTERNATIVE
+};
+
+
+#if defined(LWS_WITH_TLS)
+
+typedef SSL lws_tls_conn;
+typedef SSL_CTX lws_tls_ctx;
+typedef BIO lws_tls_bio;
+typedef X509 lws_tls_x509;
+
+#if defined(LWS_WITH_NETWORK)
+#include "private-network.h"
+#endif
+
+LWS_EXTERN int
+lws_context_init_ssl_library(const struct lws_context_creation_info *info);
+LWS_EXTERN void
+lws_context_deinit_ssl_library(struct lws_context *context);
+#define LWS_SSL_ENABLED(vh) (vh && vh->tls.use_ssl)
+
+extern const struct lws_tls_ops tls_ops_openssl, tls_ops_mbedtls;
+
+struct lws_ec_valid_curves {
+ int id;
+ const char *jwa_name; /* list terminates with NULL jwa_name */
+};
+
+LWS_EXTERN enum lws_tls_extant
+lws_tls_use_any_upgrade_check_extant(const char *name);
+LWS_EXTERN int openssl_websocket_private_data_index;
+
+
+LWS_EXTERN void
+lws_tls_err_describe_clear(void);
+
+LWS_EXTERN int
+lws_tls_openssl_cert_info(X509 *x509, enum lws_tls_cert_info type,
+ union lws_tls_cert_info_results *buf, size_t len);
+LWS_EXTERN int
+lws_tls_check_all_cert_lifetimes(struct lws_context *context);
+
+LWS_EXTERN int
+lws_tls_alloc_pem_to_der_file(struct lws_context *context, const char *filename,
+ const char *inbuf, lws_filepos_t inlen,
+ uint8_t **buf, lws_filepos_t *amount);
+LWS_EXTERN char *
+lws_ssl_get_error_string(int status, int ret, char *buf, size_t len);
+
+int
+lws_gencrypto_bits_to_bytes(int bits);
+
+void
+lws_gencrypto_destroy_elements(struct lws_gencrypto_keyelem *el, int m);
+
+/* genec */
+
+struct lws_gencrypto_keyelem;
+struct lws_ec_curves;
+
+LWS_EXTERN const struct lws_ec_curves lws_ec_curves[4];
+const struct lws_ec_curves *
+lws_genec_curve(const struct lws_ec_curves *table, const char *name);
+LWS_VISIBLE void
+lws_genec_destroy_elements(struct lws_gencrypto_keyelem *el);
+int
+lws_gencrypto_mbedtls_rngf(void *context, unsigned char *buf, size_t len);
+
+int
+lws_genec_confirm_curve_allowed_by_tls_id(const char *allowed, int id,
+ struct lws_jwk *jwk);
+
+#endif
+#endif
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*
- * This is included from core/private.h if LWS_WITH_TLS
+ * This is included from private-lib-core.h if LWS_WITH_TLS
*/
struct lws_context_per_thread;
+++ /dev/null
-/*
- * 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
- *
- * This is included from core/private.h if LWS_WITH_TLS
- */
-
-#if !defined(__LWS_TLS_PRIVATE_H__)
-#define __LWS_TLS_PRIVATE_H__
-
-
-#if defined(LWS_WITH_TLS)
-
-#if defined(USE_WOLFSSL)
- #if defined(USE_OLD_CYASSL)
- #if defined(_WIN32)
- #include <IDE/WIN/user_settings.h>
- #include <cyassl/ctaocrypt/settings.h>
- #else
- #include <cyassl/options.h>
- #endif
- #include <cyassl/openssl/ssl.h>
- #include <cyassl/error-ssl.h>
- #else
- #if defined(_WIN32)
- #include <IDE/WIN/user_settings.h>
- #include <wolfssl/wolfcrypt/settings.h>
- #else
- #include <wolfssl/options.h>
- #endif
- #include <wolfssl/openssl/ssl.h>
- #include <wolfssl/error-ssl.h>
- #define OPENSSL_NO_TLSEXT
- #endif /* not USE_OLD_CYASSL */
-#else /* WOLFSSL */
- #if defined(LWS_WITH_ESP32)
- #define OPENSSL_NO_TLSEXT
- #if !defined(LWS_AMAZON_RTOS)
- /* AMAZON RTOS has its own setting via MTK_MBEDTLS_CONFIG_FILE */
- #undef MBEDTLS_CONFIG_FILE
- #define MBEDTLS_CONFIG_FILE <mbedtls/esp_config.h>
- #endif
- #include <mbedtls/ssl.h>
- #include <mbedtls/aes.h>
- #include <mbedtls/gcm.h>
- #include <mbedtls/x509_crt.h>
- #include "tls/mbedtls/wrapper/include/openssl/ssl.h" /* wrapper !!!! */
- #else /* not esp32 */
- #if defined(LWS_WITH_MBEDTLS)
- #include <mbedtls/ssl.h>
- #include <mbedtls/aes.h>
- #include <mbedtls/gcm.h>
- #include <mbedtls/x509_crt.h>
- #include <mbedtls/x509_csr.h>
- #include <mbedtls/ecp.h>
- #include <mbedtls/ecdsa.h>
- #include "tls/mbedtls/wrapper/include/openssl/ssl.h" /* wrapper !!!! */
- #else
- #include <openssl/ssl.h>
- #include <openssl/evp.h>
- #include <openssl/err.h>
- #include <openssl/md5.h>
- #include <openssl/sha.h>
- #include <openssl/rsa.h>
- #include <openssl/bn.h>
- #include <openssl/aes.h>
- #ifdef LWS_HAVE_OPENSSL_ECDH_H
- #include <openssl/ecdh.h>
- #endif
- #if !defined(LWS_HAVE_EVP_MD_CTX_free)
- #define EVP_MD_CTX_free EVP_MD_CTX_destroy
- #endif
- #include <openssl/x509v3.h>
- #endif /* not mbedtls */
- #if defined(OPENSSL_VERSION_NUMBER)
- #if (OPENSSL_VERSION_NUMBER < 0x0009080afL)
-/*
- * later openssl defines this to negate the presence of tlsext... but it was
- * only introduced at 0.9.8j. Earlier versions don't know it exists so don't
- * define it... making it look like the feature exists...
- */
- #define OPENSSL_NO_TLSEXT
- #endif
- #endif
- #endif /* not ESP32 */
-#endif /* not USE_WOLFSSL */
-
-#endif /* LWS_WITH_TLS */
-
-enum lws_tls_extant {
- LWS_TLS_EXTANT_NO,
- LWS_TLS_EXTANT_YES,
- LWS_TLS_EXTANT_ALTERNATIVE
-};
-
-
-#if defined(LWS_WITH_TLS)
-
-typedef SSL lws_tls_conn;
-typedef SSL_CTX lws_tls_ctx;
-typedef BIO lws_tls_bio;
-typedef X509 lws_tls_x509;
-
-#if defined(LWS_WITH_NETWORK)
-#include "tls/private-network.h"
-#endif
-
-LWS_EXTERN int
-lws_context_init_ssl_library(const struct lws_context_creation_info *info);
-LWS_EXTERN void
-lws_context_deinit_ssl_library(struct lws_context *context);
-#define LWS_SSL_ENABLED(vh) (vh && vh->tls.use_ssl)
-
-extern const struct lws_tls_ops tls_ops_openssl, tls_ops_mbedtls;
-
-struct lws_ec_valid_curves {
- int id;
- const char *jwa_name; /* list terminates with NULL jwa_name */
-};
-
-LWS_EXTERN enum lws_tls_extant
-lws_tls_use_any_upgrade_check_extant(const char *name);
-LWS_EXTERN int openssl_websocket_private_data_index;
-
-
-LWS_EXTERN void
-lws_tls_err_describe_clear(void);
-
-LWS_EXTERN int
-lws_tls_openssl_cert_info(X509 *x509, enum lws_tls_cert_info type,
- union lws_tls_cert_info_results *buf, size_t len);
-LWS_EXTERN int
-lws_tls_check_all_cert_lifetimes(struct lws_context *context);
-
-LWS_EXTERN int
-lws_tls_alloc_pem_to_der_file(struct lws_context *context, const char *filename,
- const char *inbuf, lws_filepos_t inlen,
- uint8_t **buf, lws_filepos_t *amount);
-LWS_EXTERN char *
-lws_ssl_get_error_string(int status, int ret, char *buf, size_t len);
-
-int
-lws_gencrypto_bits_to_bytes(int bits);
-
-void
-lws_gencrypto_destroy_elements(struct lws_gencrypto_keyelem *el, int m);
-
-/* genec */
-
-struct lws_gencrypto_keyelem;
-struct lws_ec_curves;
-
-LWS_EXTERN const struct lws_ec_curves lws_ec_curves[4];
-const struct lws_ec_curves *
-lws_genec_curve(const struct lws_ec_curves *table, const char *name);
-LWS_VISIBLE void
-lws_genec_destroy_elements(struct lws_gencrypto_keyelem *el);
-int
-lws_gencrypto_mbedtls_rngf(void *context, unsigned char *buf, size_t len);
-
-int
-lws_genec_confirm_curve_allowed_by_tls_id(const char *allowed, int id,
- struct lws_jwk *jwk);
-
-#endif
-#endif
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
int
lws_ssl_client_connect1(struct lws *wsi)
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
/*
* fakes POLLIN on all tls guys with buffered rx
* MA 02110-1301 USA
*/
-#include "core/private.h"
+#include "private-lib-core.h"
#if defined(LWS_WITH_MBEDTLS) || (defined(OPENSSL_VERSION_NUMBER) && \
OPENSSL_VERSION_NUMBER >= 0x10002000L)
* MA 02110-1301 USA
*/
-#include "core/private.h"
-#include "tls/private.h"
+#include "private-lib-core.h"
+#include "private-lib-tls.h"
#if !defined(LWS_PLAT_OPTEE) && !defined(OPTEE_DEV_KIT)
#if defined(LWS_WITH_ESP32) && !defined(LWS_AMAZON_RTOS)
* 4) LWS_TLS_EXTANT_YES: The certs are present with the correct name and we
* have the rights to read them.
*/
-#if !defined(LWS_AMAZON_RTOS)
+
enum lws_tls_extant
lws_tls_use_any_upgrade_check_extant(const char *name)
{
-#if !defined(LWS_PLAT_OPTEE)
+#if !defined(LWS_PLAT_OPTEE) && !defined(LWS_AMAZON_RTOS)
int n;
#endif
return LWS_TLS_EXTANT_YES;
}
-#endif
-