#include <stdarg.h>
#endif
+#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(LWS_WITH_ESP8266)
struct sockaddr_in;
#define LWS_POSIX 0
#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
#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>
#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>
#include <netdb.h>
#define LWS_INVALID_FILE -1
#else
-#define getdtablesize() (20)
+#define getdtablesize() (30)
#if defined(LWS_WITH_ESP32)
#define LWS_INVALID_FILE NULL
#else
#include <uv-version.h>
#endif
#endif /* LWS_USE_LIBUV */
+#ifdef LWS_USE_LIBEVENT
+#include <event2/event.h>
+#endif /* LWS_USE_LIBEVENT */
#ifndef LWS_EXTERN
#define LWS_EXTERN extern
#include <wolfssl/error-ssl.h>
#endif /* not USE_OLD_CYASSL */
#else
-#if defined(LWS_USE_POLARSSL)
-#include <polarssl/ssl.h>
-struct lws_polarssl_context {
- x509_crt ca; /**< ca */
- x509_crt certificate; /**< cert */
- rsa_context key; /**< key */
-};
-typedef struct lws_polarssl_context SSL_CTX;
-typedef ssl_context SSL;
-#else
#include <openssl/ssl.h>
+#if !defined(LWS_WITH_ESP32)
#include <openssl/err.h>
-#endif /* not USE_POLARSSL */
+#endif
#endif /* not USE_WOLFSSL */
#endif
#endif
+static LWS_INLINE int lws_is_be(void) {
+ const int probe = ~0xff;
+
+ return *(const char *)&probe;
+}
+
/**
* lws_set_log_level() - Set the logging bitfield
* \param level: OR together the LLL_ debug contexts you want output from
#if defined(LWS_WITH_ESP32)
typedef int lws_sockfd_type;
-typedef void * lws_filefd_type;
+typedef int lws_filefd_type;
#define lws_sockfd_valid(sfd) (sfd >= 0)
struct pollfd {
lws_sockfd_type fd; /**< fd related to */
#define POLLHUP 0x0010
#define POLLNVAL 0x0020
+#include <freertos/FreeRTOS.h>
+#include <freertos/event_groups.h>
+#include <string.h>
+#include "esp_wifi.h"
+#include "esp_system.h"
+#include "esp_event.h"
+#include "esp_event_loop.h"
+#include "nvs.h"
+#include "driver/gpio.h"
+#include "esp_spi_flash.h"
#include "freertos/timers.h"
#if !defined(CONFIG_FREERTOS_HZ)
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;
xTimerDelete(*(uv_timer_t *)h, 0);
}
+/* ESP32 helper declarations */
+
+#include <mdns.h>
+#include <esp_partition.h>
+
+#define LWS_PLUGIN_STATIC
+#define LWS_MAGIC_REBOOT_TYPE_ADS 0x50001ffc
+#define LWS_MAGIC_REBOOT_TYPE_REQ_FACTORY 0xb00bcafe
+#define LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY 0xfaceb00b
+#define LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY_BUTTON 0xf0cedfac
+
+
+/* user code provides these */
+extern void
+lws_esp32_identify_physical_device(void);
+/* lws-plat-esp32 provides these */
+
+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];
+ char sta_mask[16];
+ char sta_gw[16];
+ 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 {
+ uint32_t romfs;
+ uint32_t romfs_len;
+ uint32_t json;
+ uint32_t json_len;
+};
+
+extern struct lws_esp32 lws_esp32;
+
+extern esp_err_t
+lws_esp32_event_passthru(void *ctx, system_event_t *event);
+extern void
+lws_esp32_wlan_config(void);
+extern void
+lws_esp32_wlan_start_ap(void);
+extern void
+lws_esp32_wlan_start_station(void);
+struct lws_context_creation_info;
+extern void
+lws_esp32_set_creation_defaults(struct lws_context_creation_info *info);
+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;
#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 {
*/
///@{
+struct lws_ssl_info {
+ int where;
+ int ret;
+};
/*
* NOTE: These public enums are part of the abi. If you want to add one,
* 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,
/**< 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*/
/****** add new things just above ---^ ******/
* be able to consume it all without having to return to the event
* loop. That is supported in lws.
*
- * This also controls how much may be sent at once at the moment,
- * although this is likely to change.
+ * If .tx_packet_size is 0, this also controls how much may be sent at once
+ * for backwards compatibility.
*/
unsigned int id;
/**< ignored by lws, but useful to contain user information bound
* capability flags based on selected protocol version, etc. */
void *user; /**< ignored by lws, but user code can pass a pointer
here it can later access from the protocol callback */
+ size_t tx_packet_size;
+ /**< 0 indicates restrict send() size to .rx_buffer_size for backwards-
+ * compatibility.
+ * If greater than zero, a single send() is restricted to this amount
+ * and any remainder is buffered by lws and sent afterwards also in
+ * these size chunks. Since that is expensive, it's preferable
+ * to restrict one fragment you are trying to send to match this
+ * size.
+ */
/* Add new things just above here ---^
* This is part of the ABI, don't needlessly break compatibility */
* the context, only the string you give in the client connect
* info for .origin (if any) will be used directly.
*/
+ LWS_SERVER_OPTION_FALLBACK_TO_RAW = (1 << 20),
+ /**< (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 ---^ ******/
};
#define lws_check_opt(c, f) (((c) & (f)) == (f))
+struct lws_plat_file_ops;
+
/** struct lws_context_creation_info - parameters to create context and /or vhost with
*
* This is also used to create vhosts.... if LWS_SERVER_OPTION_EXPLICIT_VHOSTS
/**< 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 */
* or you can leave it as NULL to get "DEFAULT" */
#endif
+ const struct lws_plat_file_ops *fops;
+ /**< CONTEXT: NULL, or pointer to an array of fops structs, terminated
+ * by a sentinel with NULL .open.
+ *
+ * If NULL, lws provides just the platform file operations struct for
+ * backwards compatibility.
+ */
+ 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
*
* 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.
+ */
void *_unused[8]; /**< dummy */
};
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;
* 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 */
* 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
LWS_VISIBLE LWS_EXTERN int
lws_init_vhost_client_ssl(const struct lws_context_creation_info *info,
struct lws_vhost *vhost);
-
/**
* lws_http_client_read() - consume waiting received http client data
*
LWS_VISIBLE LWS_EXTERN int
lws_serve_http_file(struct lws *wsi, const char *file, const char *content_type,
const char *other_headers, int other_headers_len);
+
LWS_VISIBLE LWS_EXTERN int
lws_serve_http_file_fragment(struct lws *wsi);
//@}
HTTP_STATUS_MOVED_PERMANENTLY = 301,
HTTP_STATUS_FOUND = 302,
HTTP_STATUS_SEE_OTHER = 303,
+ HTTP_STATUS_NOT_MODIFIED = 304,
HTTP_STATUS_BAD_REQUEST = 400,
HTTP_STATUS_UNAUTHORIZED,
_WSI_TOKEN_CLIENT_HOST,
_WSI_TOKEN_CLIENT_ORIGIN,
_WSI_TOKEN_CLIENT_METHOD,
+ _WSI_TOKEN_CLIENT_IFACE,
/* always last real token index*/
WSI_TOKEN_COUNT,
* and fail with nonzero return.
*/
///@{
+
+#define LWSAHH_CODE_MASK ((1 << 16) - 1)
+#define LWSAHH_FLAG_NO_SERVER_NAME (1 << 30)
+
/**
* lws_add_http_header_status() - add the HTTP response status code
*
* \param p: pointer to current position in buffer pointer
* \param end: pointer to end of buffer
*
- * Adds the initial response code, so should be called first
+ * Adds the initial response code, so should be called first.
+ *
+ * Code may additionally take OR'd flags:
+ *
+ * LWSAHH_FLAG_NO_SERVER_NAME: don't apply server name header this time
*/
LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
lws_add_http_header_status(struct lws *wsi,
const unsigned char *value, int length,
unsigned char **p, unsigned char *end);
/**
- * lws_add_http_header_by_name() - append content-length helper
+ * lws_add_http_header_content_length() - append content-length helper
*
* \param wsi: the connection to check
* \param content_length: the content length to use
*/
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
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 */
///@}
+/*! \defgroup event libevent helpers
+ *
+ * ##libevent helpers
+ *
+ * APIs specific to libevent event loop itegration
+ */
+///@{
+
+#ifdef LWS_USE_LIBEVENT
+typedef void (lws_event_signal_cb_t) (evutil_socket_t sock_fd, short revents,
+ void *ctx);
+
+LWS_VISIBLE LWS_EXTERN int
+lws_event_sigint_cfg(struct lws_context *context, int use_event_sigint,
+ lws_event_signal_cb_t cb);
+
+LWS_VISIBLE LWS_EXTERN int
+lws_event_initloop(struct lws_context *context, struct event_base *loop,
+ int tsi);
+
+LWS_VISIBLE LWS_EXTERN void
+lws_event_sigint_cb(evutil_socket_t sock_fd, short revents,
+ void *ctx);
+#endif /* LWS_USE_LIBEVENT */
+
+///@}
+
/*! \defgroup timeout Connection timeouts
APIs related to setting connection timeouts
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,
/****** add new things just above ---^ ******/
};
* \param reason: Callback reason index
*
* - Which: connections using this protocol on ALL VHOSTS
- * - When: when the individual connection becomes writeable
+ * - When: before returning
* - What: reason
+ *
+ * This isn't normally what you want... normally any update of connection-
+ * specific information can wait until a network-related callback like rx,
+ * writable, or close.
*/
LWS_VISIBLE LWS_EXTERN int
lws_callback_all_protocol(struct lws_context *context,
lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd);
typedef enum {
- LWS_ADOPT_HTTP = 1, /* absent implies RAW */
- LWS_ADOPT_SOCKET = 2, /* absent implies file descriptor */
- LWS_ADOPT_ALLOW_SSL = 4 /* if set requires LWS_ADOPT_SOCKET */
+ 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_adoption_type;
typedef union {
* \param type: OR-ed combinations of lws_adoption_type flags
* \param fd: union with either .sockfd or .filefd set
* \param vh_prot_name: NULL or vh protocol name to bind raw connection to
+* \param parent: NULL or struct lws to attach new_wsi to as a child
*
* Either returns new wsi bound to accept_fd, or closes accept_fd and
* returns NULL, having cleaned up any new wsi pieces.
*
* If LWS_ADOPT_SOCKET is set, LWS adopts the socket in http serving mode, it's
* ready to accept an upgrade to ws or just serve http.
+*
+* 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_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type,
- lws_sock_file_fd_type fd, const char *vh_prot_name);
-
+ lws_sock_file_fd_type fd, const char *vh_prot_name,
+ struct lws *parent);
/**
* lws_adopt_socket_readbuf() - adopt foreign socket and first rx as if listen socket accepted it
///@{
/**
+ * 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
* 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
LCHS_LF1,
LCHS_CR2,
LCHS_LF2,
+ LHCS_RESPONSE,
+ LHCS_DUMP_HEADERS,
LHCS_PAYLOAD,
LCHS_SINGLE_0A,
};
#if defined(LWS_WITH_ESP32)
/* sdk preprocessor defs? compiler issue? gets confused with member names */
-#define LWS_FOP_OPEN _open
-#define LWS_FOP_CLOSE _close
-#define LWS_FOP_SEEK_CUR _seek_cur
-#define LWS_FOP_READ _read
-#define LWS_FOP_WRITE _write
+#define LWS_FOP_OPEN _open
+#define LWS_FOP_CLOSE _close
+#define LWS_FOP_SEEK_CUR _seek_cur
+#define LWS_FOP_READ _read
+#define LWS_FOP_WRITE _write
#else
-#define LWS_FOP_OPEN open
-#define LWS_FOP_CLOSE close
-#define LWS_FOP_SEEK_CUR seek_cur
-#define LWS_FOP_READ read
-#define LWS_FOP_WRITE write
+#define LWS_FOP_OPEN open
+#define LWS_FOP_CLOSE close
+#define LWS_FOP_SEEK_CUR seek_cur
+#define LWS_FOP_READ read
+#define LWS_FOP_WRITE write
#endif
#define LWS_FOP_FLAGS_MASK ((1 << 23) - 1)
#define LWS_FOP_FLAG_COMPR_ACCEPTABLE_GZIP (1 << 24)
#define LWS_FOP_FLAG_COMPR_IS_GZIP (1 << 25)
+#define LWS_FOP_FLAG_MOD_TIME_VALID (1 << 26)
+#define LWS_FOP_FLAG_VIRTUAL (1 << 27)
struct lws_plat_file_ops;
+
struct lws_fop_fd {
- lws_filefd_type fd;
- struct lws_plat_file_ops *fops;
- void *filesystem_priv;
+ lws_filefd_type fd;
+ /**< real file descriptor related to the file... */
+ const struct lws_plat_file_ops *fops;
+ /**< fops that apply to this fop_fd */
+ void *filesystem_priv;
+ /**< ignored by lws; owned by the fops handlers */
+ lws_filepos_t pos;
+ /**< generic "position in file" */
+ lws_filepos_t len;
+ /**< generic "length of file" */
+ lws_fop_flags_t flags;
+ /**< copy of the returned flags */
+ uint32_t mod_time;
+ /**< optional "modification time of file", only valid if .open()
+ * set the LWS_FOP_FLAG_MOD_TIME_VALID flag */
};
-#if defined(WIN32) || defined(_WIN32)
-/* ... */
-#if !defined(ssize_t)
-typedef SSIZE_T ssize_t;
-#endif
-/* !!! >:-[ */
-typedef unsigned __int32 uint32_t;
-typedef unsigned __int8 uint8_t;
-#endif
typedef struct lws_fop_fd *lws_fop_fd_t;
-typedef size_t lws_filepos_t;
-typedef ssize_t lws_fileofs_t;
-typedef uint32_t lws_fop_flags_t;
+
+struct lws_fops_index {
+ const char *sig; /* NULL or vfs signature, eg, ".zip/" */
+ uint8_t len; /* length of above string */
+};
struct lws_plat_file_ops {
- lws_fop_fd_t (*LWS_FOP_OPEN)(struct lws_plat_file_ops *fops,
- const char *filename,
- lws_filepos_t *filelen,
+ lws_fop_fd_t (*LWS_FOP_OPEN)(const struct lws_plat_file_ops *fops,
+ const char *filename, const char *vpath,
lws_fop_flags_t *flags);
/**< Open file (always binary access if plat supports it)
- * filelen is filled on exit to be the length of the file
+ * vpath may be NULL, or if the fops understands it, the point at which
+ * the filename's virtual part starts.
* *flags & LWS_FOP_FLAGS_MASK should be set to O_RDONLY or O_RDWR.
* If the file may be gzip-compressed,
* LWS_FOP_FLAG_COMPR_ACCEPTABLE_GZIP is set. If it actually is
* gzip-compressed, then the open handler should OR
* LWS_FOP_FLAG_COMPR_IS_GZIP on to *flags before returning.
*/
- int (*LWS_FOP_CLOSE)(lws_fop_fd_t fop_fd);
- /**< close file */
+ int (*LWS_FOP_CLOSE)(lws_fop_fd_t *fop_fd);
+ /**< close file AND set the pointer to NULL */
lws_fileofs_t (*LWS_FOP_SEEK_CUR)(lws_fop_fd_t fop_fd,
lws_fileofs_t offset_from_cur_pos);
/**< seek from current position */
int (*LWS_FOP_WRITE)(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
uint8_t *buf, lws_filepos_t len);
/**< Write to file, on exit *amount is set to amount actually written */
- const char *path_prefix;
- /**< Optional, NULL or filesystem namespace prefix matching this fops */
+
+ struct lws_fops_index fi[3];
+ /**< vfs path signatures implying use of this fops */
+
+ const struct lws_plat_file_ops *next;
+ /**< NULL or next fops in list */
/* Add new things just above here ---^
* This is part of the ABI, don't needlessly break compatibility */
LWS_VISIBLE LWS_EXTERN struct lws_plat_file_ops * LWS_WARN_UNUSED_RESULT
lws_get_fops(struct lws_context *context);
LWS_VISIBLE LWS_EXTERN void
-lws_set_fops(struct lws_context *context, struct lws_plat_file_ops *fops);
+lws_set_fops(struct lws_context *context, const struct lws_plat_file_ops *fops);
+/**
+ * lws_vfs_tell() - get current file position
+ *
+ * \param fop_fd: fop_fd we are asking about
+ */
+LWS_VISIBLE LWS_EXTERN lws_filepos_t LWS_WARN_UNUSED_RESULT
+lws_vfs_tell(lws_fop_fd_t fop_fd);
+/**
+ * lws_vfs_get_length() - get current file total length in bytes
+ *
+ * \param fop_fd: fop_fd we are asking about
+ */
+LWS_VISIBLE LWS_EXTERN lws_filepos_t LWS_WARN_UNUSED_RESULT
+lws_vfs_get_length(lws_fop_fd_t fop_fd);
+/**
+ * lws_vfs_get_mod_time() - get time file last modified
+ *
+ * \param fop_fd: fop_fd we are asking about
+ */
+LWS_VISIBLE LWS_EXTERN uint32_t LWS_WARN_UNUSED_RESULT
+lws_vfs_get_mod_time(lws_fop_fd_t fop_fd);
+/**
+ * lws_vfs_file_seek_set() - seek relative to start of file
+ *
+ * \param fop_fd: fop_fd we are seeking in
+ * \param offset: offset from start of file
+ */
+LWS_VISIBLE LWS_EXTERN lws_fileofs_t
+lws_vfs_file_seek_set(lws_fop_fd_t fop_fd, lws_fileofs_t offset);
/**
- * lws_plat_file_open() - file open operations
+ * lws_vfs_file_seek_end() - seek relative to end of file
+ *
+ * \param fop_fd: fop_fd we are seeking in
+ * \param offset: offset from start of file
+ */
+LWS_VISIBLE LWS_EXTERN lws_fileofs_t
+lws_vfs_file_seek_end(lws_fop_fd_t fop_fd, lws_fileofs_t offset);
+
+extern struct lws_plat_file_ops fops_zip;
+
+/**
+ * lws_plat_file_open() - open vfs filepath
*
* \param fops: file ops struct that applies to this descriptor
- * \param filename: filename to open
- * \param filelen: length of file (filled in by call)
+ * \param vfs_path: filename to open
* \param flags: pointer to open flags
*
+ * The vfs_path is scanned for known fops signatures, and the open directed
+ * to any matching fops open.
+ *
+ * User code should use this api to perform vfs opens.
+ *
* returns semi-opaque handle
*/
-static LWS_INLINE lws_fop_fd_t LWS_WARN_UNUSED_RESULT
-lws_plat_file_open(struct lws_plat_file_ops *fops, const char *filename,
- lws_filepos_t *filelen, lws_fop_flags_t *flags)
-{
- return fops->LWS_FOP_OPEN(fops, filename, filelen, flags);
-}
+LWS_VISIBLE LWS_EXTERN lws_fop_fd_t LWS_WARN_UNUSED_RESULT
+lws_vfs_file_open(const struct lws_plat_file_ops *fops, const char *vfs_path,
+ lws_fop_flags_t *flags);
/**
* lws_plat_file_close() - close file
* \param fop_fd: file handle to close
*/
static LWS_INLINE int
-lws_plat_file_close(lws_fop_fd_t fop_fd)
+lws_vfs_file_close(lws_fop_fd_t *fop_fd)
{
- return fop_fd->fops->LWS_FOP_CLOSE(fop_fd);
+ return (*fop_fd)->fops->LWS_FOP_CLOSE(fop_fd);
}
/**
* \param offset: position to seek to
*/
static LWS_INLINE lws_fileofs_t
-lws_plat_file_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset)
+lws_vfs_file_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset)
{
return fop_fd->fops->LWS_FOP_SEEK_CUR(fop_fd, offset);
}
* \param len: max length
*/
static LWS_INLINE int LWS_WARN_UNUSED_RESULT
-lws_plat_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
+lws_vfs_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
uint8_t *buf, lws_filepos_t len)
{
return fop_fd->fops->LWS_FOP_READ(fop_fd, amount, buf, len);
* \param len: max length
*/
static LWS_INLINE int LWS_WARN_UNUSED_RESULT
-lws_plat_file_write(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
+lws_vfs_file_write(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
uint8_t *buf, lws_filepos_t len)
{
return fop_fd->fops->LWS_FOP_WRITE(fop_fd, amount, buf, len);
}
+
+/* these are the platform file operations implementations... they can
+ * be called directly and used in fops arrays
+ */
+
+LWS_VISIBLE LWS_EXTERN lws_fop_fd_t
+_lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
+ const char *vpath, lws_fop_flags_t *flags);
+LWS_VISIBLE LWS_EXTERN int
+_lws_plat_file_close(lws_fop_fd_t *fop_fd);
+LWS_VISIBLE LWS_EXTERN lws_fileofs_t
+_lws_plat_file_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset);
+LWS_VISIBLE LWS_EXTERN int
+_lws_plat_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
+ uint8_t *buf, lws_filepos_t len);
+LWS_VISIBLE LWS_EXTERN int
+_lws_plat_file_write(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
+ uint8_t *buf, lws_filepos_t len);
+
+LWS_VISIBLE LWS_EXTERN int
+lws_alloc_vfs_file(struct lws_context *context, const char *filename, uint8_t **buf,
+ lws_filepos_t *amount);
//@}
/** \defgroup smtp
#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