ah: allow configurable ah hold timeout
[platform/upstream/libwebsockets.git] / lib / libwebsockets.h
index 2a9fb3a..ef8efca 100644 (file)
@@ -33,6 +33,12 @@ extern "C" {
 #include <stdarg.h>
 #endif
 
+#include "lws_config.h"
+
+/*
+ * CARE: everything using cmake defines needs to be below here
+ */
+
 #if defined(LWS_WITH_ESP8266)
 struct sockaddr_in;
 #define LWS_POSIX 0
@@ -40,7 +46,12 @@ struct sockaddr_in;
 #define LWS_POSIX 1
 #endif
 
-#include "lws_config.h"
+#if defined(LWS_HAS_INTPTR_T)
+#include <stdint.h>
+#define lws_intptr_t intptr_t
+#else
+typedef unsigned long long lws_intptr_t;
+#endif
 
 #if defined(WIN32) || defined(_WIN32)
 #ifndef WIN32_LEAN_AND_MEAN
@@ -84,6 +95,9 @@ struct sockaddr_in;
 
 #define LWS_INVALID_FILE INVALID_HANDLE_VALUE
 #define LWS_O_RDONLY _O_RDONLY
+#define LWS_O_WRONLY _O_WRONLY
+#define LWS_O_CREAT _O_CREAT
+#define LWS_O_TRUNC _O_TRUNC
 
 #if !defined(__MINGW32__) && (!defined(_MSC_VER) || _MSC_VER < 1900) /* Visual Studio 2015 already defines this in <stdio.h> */
 #define lws_snprintf _snprintf
@@ -93,8 +107,15 @@ struct sockaddr_in;
 #define __func__ __FUNCTION__
 #endif
 
+#if !defined(__MINGW32__) &&(!defined(_MSC_VER) || _MSC_VER < 1900) && !defined(snprintf)
+#define snprintf(buf,len, format,...) _snprintf_s(buf, len,len, format, __VA_ARGS__)
+#endif
+
 #else /* NOT WIN32 */
 #include <unistd.h>
+#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
+#include <sys/capability.h>
+#endif
 
 #if defined(__NetBSD__) || defined(__FreeBSD__)
 #include <netinet/in.h>
@@ -102,6 +123,9 @@ struct sockaddr_in;
 
 #define LWS_INLINE inline
 #define LWS_O_RDONLY O_RDONLY
+#define LWS_O_WRONLY O_WRONLY
+#define LWS_O_CREAT O_CREAT
+#define LWS_O_TRUNC O_TRUNC
 
 #if !defined(LWS_WITH_ESP8266) && !defined(OPTEE_TA) && !defined(LWS_WITH_ESP32)
 #include <poll.h>
@@ -502,7 +526,7 @@ extern void esp32_uvtimer_cb(TimerHandle_t t);
 
 static inline void uv_timer_start(uv_timer_t *t, uv_cb_t *cb, int first, int rep)
 {
-       struct timer_mapping *tm = malloc(sizeof(*tm));
+       struct timer_mapping *tm = (struct timer_mapping *)malloc(sizeof(*tm));
 
        if (!tm)
                return;
@@ -537,7 +561,6 @@ static inline void uv_close(uv_handle_t *h, void *v)
 #define LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY 0xfaceb00b
 #define LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY_BUTTON 0xf0cedfac
 
-static inline uint32_t lws_esp32_get_reboot_type(void) { uint32_t *p = (uint32_t *)LWS_MAGIC_REBOOT_TYPE_ADS; return *p; }
 
 /* user code provides these */
 
@@ -546,8 +569,35 @@ lws_esp32_identify_physical_device(void);
 
 /* lws-plat-esp32 provides these */
 
-extern void (*lws_cb_scan_done)(void *);
-extern void *lws_cb_scan_done_arg;
+typedef void (*lws_cb_scan_done)(uint16_t count, wifi_ap_record_t *recs, void *arg);
+
+enum genled_state {
+       LWSESP32_GENLED__INIT,
+       LWSESP32_GENLED__LOST_NETWORK,
+       LWSESP32_GENLED__NO_NETWORK,
+       LWSESP32_GENLED__CONN_AP,
+       LWSESP32_GENLED__GOT_IP,
+       LWSESP32_GENLED__OK,
+};
+
+struct lws_group_member {
+       struct lws_group_member *next;
+       uint64_t last_seen;
+       char model[16];
+       char role[16];
+       char host[32];
+       char mac[20];
+       int width, height;
+       struct ip4_addr addr;
+       struct ip6_addr addrv6;
+       uint8_t flags;
+};
+
+#define LWS_SYSTEM_GROUP_MEMBER_ADD            1
+#define LWS_SYSTEM_GROUP_MEMBER_CHANGE         2
+#define LWS_SYSTEM_GROUP_MEMBER_REMOVE         3
+
+#define LWS_GROUP_FLAG_SELF 1
 
 struct lws_esp32 {
        char sta_ip[16];
@@ -556,10 +606,26 @@ struct lws_esp32 {
        char serial[16];
        char opts[16];
        char model[16];
+       char group[16];
+       char role[16];
+       char ssid[4][16];
+       char password[4][32];
+       char active_ssid[32];
        char access_pw[16];
+       char hostname[32];
+       char mac[20];
        mdns_server_t *mdns;
                char region;
                char inet;
+       char conn_ap;
+
+       enum genled_state genled;
+       uint64_t genled_t;
+
+       lws_cb_scan_done scan_consumer;
+       void *scan_consumer_arg;
+       struct lws_group_member *first;
+       int extant_group_members;
 };
 
 struct lws_esp32_image {
@@ -586,12 +652,22 @@ extern struct lws_context *
 lws_esp32_init(struct lws_context_creation_info *);
 extern int
 lws_esp32_wlan_nvs_get(int retry);
+extern esp_err_t
+lws_nvs_set_str(nvs_handle handle, const char* key, const char* value);
 extern void
 lws_esp32_restart_guided(uint32_t type);
 extern const esp_partition_t *
 lws_esp_ota_get_boot_partition(void);
 extern int
 lws_esp32_get_image_info(const esp_partition_t *part, struct lws_esp32_image *i, char *json, int json_len);
+extern int
+lws_esp32_leds_network_indication(void);
+
+extern uint32_t lws_esp32_get_reboot_type(void);
+extern uint16_t lws_esp32_sine_interp(int n);
+
+/* required in external code by esp32 plat (may just return if no leds) */
+extern void lws_esp32_leds_timer_cb(TimerHandle_t th);
 #else
 typedef int lws_sockfd_type;
 typedef int lws_filefd_type;
@@ -605,6 +681,36 @@ typedef int lws_filefd_type;
 #define LWS_POLLOUT (POLLOUT)
 #endif
 
+
+#if (defined(WIN32) || defined(_WIN32)) && !defined(__MINGW32__)
+/* ... */
+#define ssize_t SSIZE_T
+#endif
+
+#if defined(WIN32) && defined(LWS_HAVE__STAT32I64)
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
+#if defined(LWS_HAVE_STDINT_H)
+#include <stdint.h>
+#else
+#if defined(WIN32) || defined(_WIN32)
+/* !!! >:-[  */
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int16 uint16_t;
+typedef unsigned __int8 uint8_t;
+#else
+typedef unsigned int uint32_t;
+typedef unsigned short uint16_t;
+typedef unsigned char uint8_t;
+#endif
+#endif
+
+typedef unsigned long long lws_filepos_t;
+typedef long long lws_fileofs_t;
+typedef uint32_t lws_fop_flags_t;
+
 /** struct lws_pollargs - argument structure for all external poll related calls
  * passed in via 'in' */
 struct lws_pollargs {
@@ -721,6 +827,38 @@ struct lws_context;
 /* needed even with extensions disabled for create context */
 struct lws_extension;
 
+/*! \defgroup lwsmeta lws-meta
+ *
+ * ##lws-meta protocol
+ *
+ * The protocol wraps other muxed connections inside one tcp connection.
+ *
+ * Commands are assigned from 0x41 up (so they are valid unicode)
+ */
+///@{
+
+enum lws_meta_commands {
+       LWS_META_CMD_OPEN_SUBCHANNEL = 'A',
+       /**< Client requests to open new subchannel
+        */
+       LWS_META_CMD_OPEN_RESULT,
+       /**< Result of client request to open new subchannel */
+       LWS_META_CMD_CLOSE_NOTIFY,
+       /**< Notification of subchannel closure */
+       LWS_META_CMD_CLOSE_RQ,
+       /**< client requests to close a subchannel */
+       LWS_META_CMD_WRITE,
+       /**< connection writes something to specific channel index */
+
+       /****** add new things just above ---^ ******/
+};
+
+/* channel numbers are transported offset by 0x20 so they are valid unicode */
+
+#define LWS_META_TRANSPORT_OFFSET 0x20
+
+///@}
+
 /*! \defgroup usercb User Callback
  *
  * ##User protocol callback
@@ -734,6 +872,10 @@ struct lws_extension;
  */
 ///@{
 
+struct lws_ssl_info {
+       int where;
+       int ret;
+};
 
 /*
  * NOTE: These public enums are part of the abi.  If you want to add one,
@@ -954,8 +1096,7 @@ enum lws_callback_reasons {
         * and with in being the extension name, len is 0 and user is
         * valid.  Note though at this time the ESTABLISHED callback hasn't
         * happened yet so if you initialize user content there, user
-        * content during this callback might not be useful for anything.
-        * Notice this callback comes to protocols[0]. */
+        * content during this callback might not be useful for anything. */
        LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED         = 26,
        /**< When a client
         * connection is being prepared to start a handshake to a server,
@@ -1141,6 +1282,22 @@ enum lws_callback_reasons {
        /**< RAW mode file is writeable */
        LWS_CALLBACK_RAW_CLOSE_FILE                             = 66,
        /**< RAW mode wsi that adopted a file is closing */
+       LWS_CALLBACK_SSL_INFO                                   = 67,
+       /**< SSL connections only.  An event you registered an
+        * interest in at the vhost has occurred on a connection
+        * using the vhost.  @in is a pointer to a
+        * struct lws_ssl_info containing information about the
+        * event*/
+       LWS_CALLBACK_CHILD_WRITE_VIA_PARENT                     = 68,
+       /**< Child has been marked with parent_carries_io attribute, so
+        * lws_write directs the to this callback at the parent,
+        * @in is a struct lws_write_passthru containing the args
+        * the lws_write() was called with.
+        */
+       LWS_CALLBACK_CHILD_CLOSING                              = 69,
+       /**< Sent to parent to notify them a child is closing / being
+        * destroyed.  @in is the child wsi.
+        */
 
        /****** add new things just above ---^ ******/
 
@@ -1692,6 +1849,16 @@ enum lws_context_options {
        /**< (VH) if invalid http is coming in the first line,  */
        LWS_SERVER_OPTION_LIBEVENT                              = (1 << 21),
        /**< (CTX) Use libevent event loop */
+       LWS_SERVER_OPTION_ONLY_RAW                              = (1 << 22),
+       /**< (VH) All connections to this vhost / port are RAW as soon as
+        * the connection is accepted, no HTTP is going to be coming.
+        */
+       LWS_SERVER_OPTION_ALLOW_LISTEN_SHARE                    = (1 << 23),
+       /**< (VH) Set to allow multiple listen sockets on one interface +
+        * address + port.  The default is to strictly allow only one
+        * listen socket at a time.  This is automatically selected if you
+        * have multiple service threads.
+        */
 
        /****** add new things just above ---^ ******/
 };
@@ -1763,7 +1930,7 @@ struct lws_context_creation_info {
        /**< VHOST + CONTEXT: 0, or LWS_SERVER_OPTION_... bitfields */
        void *user;
        /**< CONTEXT: optional user pointer that can be recovered via the context
*             pointer using lws_context_user */
       *              pointer using lws_context_user */
        int ka_time;
        /**< CONTEXT: 0 for no TCP keepalive, otherwise apply this keepalive
         * timeout to all libwebsocket sockets, client or server */
@@ -1906,6 +2073,34 @@ struct lws_context_creation_info {
         */
        int simultaneous_ssl_restriction;
        /**< CONTEXT: 0 (no limit) or limit of simultaneous SSL sessions possible.*/
+       const char *socks_proxy_address;
+       /**< VHOST: If non-NULL, attempts to proxy via the given address.
+        * If proxy auth is required, use format "username:password\@server:port" */
+       unsigned int socks_proxy_port;
+       /**< VHOST: If socks_proxy_address was non-NULL, uses this port */
+#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
+       cap_value_t caps[4];
+       /**< CONTEXT: array holding Linux capabilities you want to
+        * continue to be available to the server after it transitions
+        * to a noprivileged user.  Usually none are needed but for, eg,
+        * .bind_iface, CAP_NET_RAW is required.  This gives you a way
+        * to still have the capability but drop root.
+        */
+       char count_caps;
+       /**< CONTEXT: count of Linux capabilities in .caps[].  0 means
+        * no capabilities will be inherited from root (the default) */
+#endif
+       int bind_iface;
+       /**< VHOST: nonzero to strictly bind sockets to the interface name in
+        * .iface (eg, "eth2"), using SO_BIND_TO_DEVICE.
+        *
+        * Requires SO_BINDTODEVICE support from your OS and CAP_NET_RAW
+        * capability.
+        *
+        * Notice that common things like access network interface IP from
+        * your local machine use your lo / loopback interface and will be
+        * disallowed by this.
+        */
 
        /* Add new things just above here ---^
         * This is part of the ABI, don't needlessly break compatibility
@@ -1914,6 +2109,15 @@ struct lws_context_creation_info {
         * members added above will see 0 (default) even if the app
         * was not built against the newer headers.
         */
+       int ssl_info_event_mask;
+       /**< VHOST: mask of ssl events to be reported on LWS_CALLBACK_SSL_INFO
+        * callback for connections on this vhost.  The mask values are of
+        * the form SSL_CB_ALERT, defined in openssl/ssl.h.  The default of
+        * 0 means no info events will be reported.
+        */
+       unsigned int timeout_secs_ah_idle;
+       /**< VHOST: seconds to allow a client to hold an ah without using it.
+        * 0 defaults to 10s. */
 
        void *_unused[8]; /**< dummy */
 };
@@ -2021,6 +2225,25 @@ lws_context_is_deprecated(struct lws_context *context);
 LWS_VISIBLE LWS_EXTERN int
 lws_set_proxy(struct lws_vhost *vhost, const char *proxy);
 
+/**
+ * lws_set_socks() - Setup socks to lws_context.
+ * \param vhost:       pointer to struct lws_vhost you want set socks for
+ * \param socks: pointer to c string containing socks in format address:port
+ *
+ * Returns 0 if socks string was parsed and socks was setup.
+ * Returns -1 if socks is NULL or has incorrect format.
+ *
+ * This is only required if your OS does not provide the socks_proxy
+ * environment variable (eg, OSX)
+ *
+ *   IMPORTANT! You should call this function right after creation of the
+ *   lws_context and before call to connect. If you call this
+ *   function after connect behavior is undefined.
+ *   This function will override proxy settings made on lws_context
+ *   creation with genenv() call.
+ */
+LWS_VISIBLE LWS_EXTERN int
+lws_set_socks(struct lws_vhost *vhost, const char *socks);
 
 struct lws_vhost;
 
@@ -2033,11 +2256,23 @@ struct lws_vhost;
  * members of the info struct.  You can create many vhosts inside one context
  * if you created the context with the option LWS_SERVER_OPTION_EXPLICIT_VHOSTS
  */
-LWS_EXTERN LWS_VISIBLE struct lws_vhost *
+LWS_VISIBLE LWS_EXTERN struct lws_vhost *
 lws_create_vhost(struct lws_context *context,
                 struct lws_context_creation_info *info);
 
 /**
+ * lws_destroy_vhost() - Destroy a vhost (virtual server context)
+ * \param vhost:       pointer to result of lws_create_vhost()
+ *
+ * This function destroys a vhost.  Normally, if you just want to exit,
+ * then lws_destroy_context() will take care of everything.  If you want
+ * to destroy an individual vhost and all connections and allocations, you
+ * can do it with this.
+ */
+LWS_VISIBLE LWS_EXTERN void
+lws_vhost_destroy(struct lws_vhost *vh);
+
+/**
  * lwsws_get_config_globals() - Parse a JSON server config file
  * \param info:                pointer to struct with parameters
  * \param d:           filepath of the config file
@@ -2144,8 +2379,8 @@ struct lws_protocol_vhost_options {
  * served from a filesystem, or it is a cgi etc.
  */
 enum lws_mount_protocols {
-       LWSMPRO_HTTP            = 0, /**< not supported yet */
-       LWSMPRO_HTTPS           = 1, /**< not supported yet */
+       LWSMPRO_HTTP            = 0, /**< http reverse proxy */
+       LWSMPRO_HTTPS           = 1, /**< https reverse proxy */
        LWSMPRO_FILE            = 2, /**< serve from filesystem directory */
        LWSMPRO_CGI             = 3, /**< pass to CGI to handle */
        LWSMPRO_REDIR_HTTP      = 4, /**< redirect to http:// url */
@@ -2278,6 +2513,9 @@ struct lws_client_connect_info {
         * even before the new wsi is returned and even if ultimately no wsi
         * is returned.
         */
+       const char *iface;
+       /**< NULL to allow routing on any interface, or interface name or IP
+        * to bind the socket to */
 
        /* Add new things just above here ---^
         * This is part of the ABI, don't needlessly break compatibility
@@ -2594,6 +2832,9 @@ lws_service_adjust_timeout(struct lws_context *context, int timeout_ms, int tsi)
 /* Backwards compatibility */
 #define lws_plat_service_tsi lws_service_tsi
 
+LWS_VISIBLE LWS_EXTERN int
+lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd);
+
 ///@}
 
 /*! \defgroup http HTTP
@@ -2875,6 +3116,7 @@ enum lws_token_indexes {
        _WSI_TOKEN_CLIENT_HOST,
        _WSI_TOKEN_CLIENT_ORIGIN,
        _WSI_TOKEN_CLIENT_METHOD,
+       _WSI_TOKEN_CLIENT_IFACE,
 
        /* always last real token index*/
        WSI_TOKEN_COUNT,
@@ -3056,7 +3298,7 @@ lws_add_http_header_by_token(struct lws *wsi, enum lws_token_indexes token,
  */
 LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
 lws_add_http_header_content_length(struct lws *wsi,
-                                  unsigned long content_length,
+                                  lws_filepos_t content_length,
                                   unsigned char **p, unsigned char *end);
 /**
  * lws_finalize_http_header() - terminate header block
@@ -3362,6 +3604,9 @@ lws_uv_getloop(struct lws_context *context, int tsi);
 
 LWS_VISIBLE LWS_EXTERN void
 lws_uv_sigint_cb(uv_signal_t *watcher, int signum);
+
+LWS_VISIBLE LWS_EXTERN void
+lws_close_all_handles_in_loop(uv_loop_t *loop);
 #endif /* LWS_USE_LIBUV */
 ///@}
 
@@ -3422,10 +3667,30 @@ enum pending_timeout {
        PENDING_TIMEOUT_WS_PONG_CHECK_SEND_PING                 = 16,
        PENDING_TIMEOUT_WS_PONG_CHECK_GET_PONG                  = 17,
        PENDING_TIMEOUT_CLIENT_ISSUE_PAYLOAD                    = 18,
+       PENDING_TIMEOUT_AWAITING_SOCKS_GREETING_REPLY           = 19,
+       PENDING_TIMEOUT_AWAITING_SOCKS_CONNECT_REPLY            = 20,
+       PENDING_TIMEOUT_AWAITING_SOCKS_AUTH_REPLY               = 21,
+       PENDING_TIMEOUT_KILLED_BY_SSL_INFO                      = 22,
+       PENDING_TIMEOUT_KILLED_BY_PARENT                        = 23,
+       PENDING_TIMEOUT_CLOSE_SEND                              = 24,
+       PENDING_TIMEOUT_HOLDING_AH                              = 25,
 
        /****** add new things just above ---^ ******/
 };
 
+#define LWS_TO_KILL_ASYNC -1
+/**< If LWS_TO_KILL_ASYNC is given as the timeout sec in a lws_set_timeout()
+ * call, then the connection is marked to be killed at the next timeout
+ * check.  This is how you should force-close the wsi being serviced if
+ * you are doing it outside the callback (where you should close by nonzero
+ * return).
+ */
+#define LWS_TO_KILL_SYNC -2
+/**< If LWS_TO_KILL_SYNC is given as the timeout sec in a lws_set_timeout()
+ * call, then the connection is closed before returning (which may delete
+ * the wsi).  This should only be used where the wsi being closed is not the
+ * wsi currently being serviced.
+ */
 /**
  * lws_set_timeout() - marks the wsi as subject to a timeout
  *
@@ -3433,7 +3698,10 @@ enum pending_timeout {
  *
  * \param wsi: Websocket connection instance
  * \param reason:      timeout reason
- * \param secs:        how many seconds
+ * \param secs:        how many seconds.  You may set to LWS_TO_KILL_ASYNC to
+ *             force the connection to timeout at the next opportunity, or
+ *             LWS_TO_KILL_SYNC to close it synchronously if you know the
+ *             wsi is not the one currently being serviced.
  */
 LWS_VISIBLE LWS_EXTERN void
 lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs);
@@ -3458,7 +3726,8 @@ lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs);
 #endif
 #define _LWS_PAD(n) (((n) % _LWS_PAD_SIZE) ? \
                ((n) + (_LWS_PAD_SIZE - ((n) % _LWS_PAD_SIZE))) : (n))
-#define LWS_PRE _LWS_PAD(4 + 10)
+/* last 2 is for lws-meta */
+#define LWS_PRE _LWS_PAD(4 + 10 + 2)
 /* used prior to 1.7 and retained for backward compatibility */
 #define LWS_SEND_BUFFER_PRE_PADDING LWS_PRE
 #define LWS_SEND_BUFFER_POST_PADDING 0
@@ -3510,6 +3779,15 @@ enum lws_write_protocol {
         * decode the content if used */
 };
 
+/* used with LWS_CALLBACK_CHILD_WRITE_VIA_PARENT */
+
+struct lws_write_passthru {
+       struct lws *wsi;
+       unsigned char *buf;
+       size_t len;
+       enum lws_write_protocol wp;
+};
+
 
 /**
  * lws_write() - Apply protocol then write data to client
@@ -3854,7 +4132,11 @@ typedef enum {
        LWS_ADOPT_RAW_FILE_DESC = 0,    /* convenience constant */
        LWS_ADOPT_HTTP = 1,             /* flag: absent implies RAW */
        LWS_ADOPT_SOCKET = 2,           /* flag: absent implies file descr */
-       LWS_ADOPT_ALLOW_SSL = 4         /* flag: if set requires LWS_ADOPT_SOCKET */
+       LWS_ADOPT_ALLOW_SSL = 4,        /* flag: if set requires LWS_ADOPT_SOCKET */
+       LWS_ADOPT_WS_PARENTIO = 8,      /* flag: ws mode parent handles IO
+                                        *   if given must be only flag
+                                        *   wsi put directly into ws mode
+                                        */
 } lws_adoption_type;
 
 typedef union {
@@ -3881,7 +4163,7 @@ typedef union {
 * parent may be NULL, if given it should be an existing wsi that will become the
 * parent of the new wsi created by this call.
 */
-LWS_VISIBLE struct lws *
+LWS_VISIBLE LWS_EXTERN struct lws *
 lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type,
                           lws_sock_file_fd_type fd, const char *vh_prot_name,
                           struct lws *parent);
@@ -4015,6 +4297,74 @@ lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr,
 ///@{
 
 /**
+ * lws_start_foreach_ll(): linkedlist iterator helper start
+ *
+ * \param type: type of iteration, eg, struct xyz *
+ * \param it: iterator var name to create
+ * \param start: start of list
+ *
+ * This helper creates an iterator and starts a while (it) {
+ * loop.  The iterator runs through the linked list starting at start and
+ * ends when it gets a NULL.
+ * The while loop should be terminated using lws_start_foreach_ll().
+ */
+#define lws_start_foreach_ll(type, it, start)\
+{ \
+       type it = start; \
+       while (it) {
+
+/**
+ * lws_end_foreach_ll(): linkedlist iterator helper end
+ *
+ * \param it: same iterator var name given when starting
+ * \param nxt: member name in the iterator pointing to next list element
+ *
+ * This helper is the partner for lws_start_foreach_ll() that ends the
+ * while loop.
+ */
+
+#define lws_end_foreach_ll(it, nxt) \
+               it = it->nxt; \
+       } \
+}
+
+/**
+ * lws_start_foreach_llp(): linkedlist pointer iterator helper start
+ *
+ * \param type: type of iteration, eg, struct xyz **
+ * \param it: iterator var name to create
+ * \param start: start of list
+ *
+ * This helper creates an iterator and starts a while (it) {
+ * loop.  The iterator runs through the linked list starting at the
+ * address of start and ends when it gets a NULL.
+ * The while loop should be terminated using lws_start_foreach_llp().
+ *
+ * This helper variant iterates using a pointer to the previous linked-list
+ * element.  That allows you to easily delete list members by rewriting the
+ * previous pointer to the element's next pointer.
+ */
+#define lws_start_foreach_llp(type, it, start)\
+{ \
+       type it = &(start); \
+       while (*(it)) {
+
+/**
+ * lws_end_foreach_llp(): linkedlist pointer iterator helper end
+ *
+ * \param it: same iterator var name given when starting
+ * \param nxt: member name in the iterator pointing to next list element
+ *
+ * This helper is the partner for lws_start_foreach_llp() that ends the
+ * while loop.
+ */
+
+#define lws_end_foreach_llp(it, nxt) \
+               it = &(*(it))->nxt; \
+       } \
+}
+
+/**
  * lws_snprintf(): snprintf that truncates the returned length too
  *
  * \param str: destination buffer
@@ -4144,6 +4494,32 @@ lws_get_parent(const struct lws *wsi);
 LWS_VISIBLE LWS_EXTERN struct lws * LWS_WARN_UNUSED_RESULT
 lws_get_child(const struct lws *wsi);
 
+/**
+ * lws_parent_carries_io() - mark wsi as needing to send messages via parent
+ *
+ * \param wsi: child lws connection
+ */
+
+LWS_VISIBLE LWS_EXTERN void
+lws_set_parent_carries_io(struct lws *wsi);
+
+LWS_VISIBLE LWS_EXTERN void *
+lws_get_opaque_parent_data(const struct lws *wsi);
+
+LWS_VISIBLE LWS_EXTERN void
+lws_set_opaque_parent_data(struct lws *wsi, void *data);
+
+LWS_VISIBLE LWS_EXTERN int
+lws_get_child_pending_on_writable(const struct lws *wsi);
+
+LWS_VISIBLE LWS_EXTERN void
+lws_clear_child_pending_on_writable(struct lws *wsi);
+
+LWS_VISIBLE LWS_EXTERN int
+lws_get_close_length(struct lws *wsi);
+
+LWS_VISIBLE LWS_EXTERN unsigned char *
+lws_get_close_payload(struct lws *wsi);
 
 /*
  * \deprecated DEPRECATED Note: this is not normally needed as a user api.
@@ -4151,7 +4527,7 @@ lws_get_child(const struct lws *wsi);
  * useful when integrating with other app poll loop service code.
  */
 LWS_VISIBLE LWS_EXTERN int
-lws_read(struct lws *wsi, unsigned char *buf, size_t len);
+lws_read(struct lws *wsi, unsigned char *buf, lws_filepos_t len);
 
 /**
  * lws_set_allocator() - custom allocator support
@@ -4181,12 +4557,21 @@ lws_send_pipe_choked(struct lws *wsi);
 
 /**
  * lws_is_final_fragment() - tests if last part of ws message
+ *
  * \param wsi: lws connection
  */
 LWS_VISIBLE LWS_EXTERN int
 lws_is_final_fragment(struct lws *wsi);
 
 /**
+ * lws_is_first_fragment() - tests if first part of ws message
+ *
+ * \param wsi: lws connection
+ */
+LWS_VISIBLE LWS_EXTERN int
+lws_is_first_fragment(struct lws *wsi);
+
+/**
  * lws_get_reserved_bits() - access reserved bits of ws frame
  * \param wsi: lws connection
  */
@@ -4323,6 +4708,8 @@ enum lws_cgi_hdr_state {
        LCHS_LF1,
        LCHS_CR2,
        LCHS_LF2,
+       LHCS_RESPONSE,
+       LHCS_DUMP_HEADERS,
        LHCS_PAYLOAD,
        LCHS_SINGLE_0A,
 };
@@ -4415,32 +4802,6 @@ lws_cgi_kill(struct lws *wsi);
 
 struct lws_plat_file_ops;
 
-#if defined(WIN32) || defined(_WIN32)
-/* ... */
-#if !defined(ssize_t)
-typedef SSIZE_T ssize_t;
-#endif
-#endif
-
-#if defined(LWS_HAVE_STDINT_H)
-#include <stdint.h>
-#else
-#if defined(WIN32) || defined(_WIN32)
-/* !!! >:-[  */
-typedef unsigned __int32 uint32_t;
-typedef unsigned __int16 uint16_t;
-typedef unsigned __int8 uint8_t;
-#else
-typedef unsigned int uint32_t;
-typedef unsigned short uint16_t;
-typedef unsigned char uint8_t;
-#endif
-#endif
-
-typedef size_t lws_filepos_t;
-typedef ssize_t lws_fileofs_t;
-typedef uint32_t lws_fop_flags_t;
-
 struct lws_fop_fd {
        lws_filefd_type                 fd;
        /**< real file descriptor related to the file... */
@@ -4766,6 +5127,56 @@ lws_email_destroy(struct lws_email *email);
 #endif
 //@}
 
+/*
+ * Stats are all uint64_t numbers that start at 0.
+ * Index names here have the convention
+ *
+ *  _C_ counter
+ *  _B_ byte count
+ *  _MS_ millisecond count
+ */
+
+enum {
+       LWSSTATS_C_CONNECTIONS, /**< count incoming connections */
+       LWSSTATS_C_API_CLOSE, /**< count calls to close api */
+       LWSSTATS_C_API_READ, /**< count calls to read from socket api */
+       LWSSTATS_C_API_LWS_WRITE, /**< count calls to lws_write API */
+       LWSSTATS_C_API_WRITE, /**< count calls to write API */
+       LWSSTATS_C_WRITE_PARTIALS, /**< count of partial writes */
+       LWSSTATS_C_WRITEABLE_CB_REQ, /**< count of writable callback requests */
+       LWSSTATS_C_WRITEABLE_CB_EFF_REQ, /**< count of effective writable callback requests */
+       LWSSTATS_C_WRITEABLE_CB, /**< count of writable callbacks */
+       LWSSTATS_C_SSL_CONNECTIONS_FAILED, /**< count of failed SSL connections */
+       LWSSTATS_C_SSL_CONNECTIONS_ACCEPTED, /**< count of accepted SSL connections */
+       LWSSTATS_C_SSL_CONNS_HAD_RX, /**< count of accepted SSL conns that have had some RX */
+       LWSSTATS_C_TIMEOUTS, /**< count of timed-out connections */
+       LWSSTATS_C_SERVICE_ENTRY, /**< count of entries to lws service loop */
+       LWSSTATS_B_READ, /**< aggregate bytes read */
+       LWSSTATS_B_WRITE, /**< aggregate bytes written */
+       LWSSTATS_B_PARTIALS_ACCEPTED_PARTS, /**< aggreate of size of accepted write data from new partials */
+       LWSSTATS_MS_SSL_CONNECTIONS_ACCEPTED_DELAY, /**< aggregate delay in accepting connection */
+       LWSSTATS_MS_WRITABLE_DELAY, /**< aggregate delay between asking for writable and getting cb */
+       LWSSTATS_MS_WORST_WRITABLE_DELAY, /**< single worst delay between asking for writable and getting cb */
+       LWSSTATS_MS_SSL_RX_DELAY, /**< aggregate delay between ssl accept complete and first RX */
+
+       /* Add new things just above here ---^
+        * This is part of the ABI, don't needlessly break compatibility */
+       LWSSTATS_SIZE
+};
+
+#if defined(LWS_WITH_STATS)
+
+LWS_VISIBLE LWS_EXTERN uint64_t
+lws_stats_get(struct lws_context *context, int index);
+LWS_VISIBLE LWS_EXTERN void
+lws_stats_log_dump(struct lws_context *context);
+#else
+static LWS_INLINE uint64_t
+lws_stats_get(struct lws_context *context, int index) { return 0; }
+static LWS_INLINE void
+lws_stats_log_dump(struct lws_context *context) { }
+#endif
+
 #ifdef __cplusplus
 }
 #endif