#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
-#if defined(LWS_USE_MBEDTLS)
-#include <mbedtls/ssl.h>
-#else
#include <openssl/ssl.h>
+#if !defined(LWS_WITH_ESP32)
#include <openssl/err.h>
-#endif /* not USE_MBEDTLS */
-#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__)
+/* ... */
+#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_pollargs - argument structure for all external poll related calls
* passed in via 'in' */
struct lws_pollargs {
* 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,
LWS_CALLBACK_RAW_WRITEABLE = 61,
/**< RAW mode connection may be written */
LWS_CALLBACK_RAW_ADOPT = 62,
- /**< RAW mode connection was adopted (equivalent to 'created') */
+ /**< RAW mode connection was adopted (equivalent to 'wsi created') */
+ LWS_CALLBACK_RAW_ADOPT_FILE = 63,
+ /**< RAW mode file was adopted (equivalent to 'wsi created') */
+ LWS_CALLBACK_RAW_RX_FILE = 64,
+ /**< RAW mode file has something to read */
+ LWS_CALLBACK_RAW_WRITEABLE_FILE = 65,
+ /**< RAW mode file is writeable */
+ LWS_CALLBACK_RAW_CLOSE_FILE = 66,
+ /**< RAW mode wsi that adopted a file is closing */
/****** add new things just above ---^ ******/
LWS_CALLBACK_USER = 1000,
- /**< user code can use any including / above without fear of clashes */
+ /**< user code can use any including above without fear of clashes */
};
* 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.
+ */
/****** 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
*
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;
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,
* 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
#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,
/****** 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_VISIBLE LWS_EXTERN struct lws *
lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd);
+
+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_adoption_type;
+
+typedef union {
+ lws_sockfd_type sockfd;
+ lws_filefd_type filefd;
+} lws_sock_file_fd_type;
+
/*
-* lws_adopt_socket_vhost2() - adopt foreign socket as if listen socket accepted it
-* for vhost, allow control over defeat SSL and raw transport mode
+* lws_adopt_descriptor_vhost() - adopt foreign socket or file descriptor
+* if socket descriptor, should already have been accepted from listen socket
+*
* \param vhost: lws vhost
-* \param accept_fd: fd of already-accepted socket to adopt
-* \param allow_ssl: 0 = no SSL even if vhost supports, 1 = SSL if vhost supports
-* \param raw: 0 = http[s]/wss[s], 1 = raw mode semantics
+* \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.
*
-* LWS adopts the socket in http serving mode, it's ready to accept an upgrade
-* to ws or just serve http.
+* 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_socket_vhost2(struct lws_vhost *vh, lws_sockfd_type accept_fd,
- int allow_ssl, int raw);
+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);
/**
* lws_adopt_socket_readbuf() - adopt foreign socket and first rx as if listen socket accepted it
lws_wsi_user(struct lws *wsi);
/**
+ * lws_wsi_set_user() - set the user data associated with the client connection
+ * \param wsi: lws connection
+ * \param user: user data
+ *
+ * By default lws allocates this and it's not legal to externally set it
+ * yourself. However client connections may have it set externally when the
+ * connection is created... if so, this api can be used to modify it at
+ * runtime additionally.
+ */
+LWS_VISIBLE LWS_EXTERN void
+lws_set_wsi_user(struct lws *wsi, void *user);
+
+/**
* lws_parse_uri: cut up prot:/ads:port/path into pieces
* Notice it does so by dropping '\0' into input string
* and the leading / on the path is consequently lost
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;
+ /**< 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 */
+};
+typedef struct lws_fop_fd *lws_fop_fd_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_filefd_type (*LWS_FOP_OPEN)(struct lws *wsi, const char *filename,
- unsigned long *filelen, int *flags);
+ 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)(struct lws *wsi, lws_filefd_type fd);
- /**< close file */
- unsigned long (*LWS_FOP_SEEK_CUR)(struct lws *wsi, lws_filefd_type fd,
- long offset_from_cur_pos);
+ 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_READ)(struct lws *wsi, lws_filefd_type fd,
- unsigned long *amount, unsigned char *buf,
- unsigned long len);
+ int (*LWS_FOP_READ)(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
+ uint8_t *buf, lws_filepos_t len);
/**< Read from file, on exit *amount is set to amount actually read */
- int (*LWS_FOP_WRITE)(struct lws *wsi, lws_filefd_type fd,
- unsigned long *amount, unsigned char *buf,
- unsigned long len);
+ 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 */
+ 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_plat_file_open() - file open operations
+ * lws_vfs_tell() - get current file position
*
- * \param wsi: connection doing the opening
- * \param filename: filename to open
- * \param filelen: length of file (filled in by call)
- * \param flags: open flags
+ * \param fop_fd: fop_fd we are asking about
*/
-static LWS_INLINE lws_filefd_type LWS_WARN_UNUSED_RESULT
-lws_plat_file_open(struct lws *wsi, const char *filename,
- unsigned long *filelen, int *flags)
-{
- return lws_get_fops(lws_get_context(wsi))->LWS_FOP_OPEN(wsi, filename,
- filelen, flags);
-}
+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_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 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
+ */
+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 wsi: connection opened by
- * \param fd: file descriptor
+ * \param fop_fd: file handle to close
*/
static LWS_INLINE int
-lws_plat_file_close(struct lws *wsi, lws_filefd_type fd)
+lws_vfs_file_close(lws_fop_fd_t *fop_fd)
{
- return lws_get_fops(lws_get_context(wsi))->LWS_FOP_CLOSE(wsi, fd);
+ return (*fop_fd)->fops->LWS_FOP_CLOSE(fop_fd);
}
/**
* lws_plat_file_seek_cur() - close file
*
- * \param wsi: connection opened by
- * \param fd: file descriptor
+ *
+ * \param fop_fd: file handle
* \param offset: position to seek to
*/
-static LWS_INLINE unsigned long
-lws_plat_file_seek_cur(struct lws *wsi, lws_filefd_type fd, long offset)
+static LWS_INLINE lws_fileofs_t
+lws_vfs_file_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset)
{
- return lws_get_fops(lws_get_context(wsi))->LWS_FOP_SEEK_CUR(wsi,
- fd, offset);
+ return fop_fd->fops->LWS_FOP_SEEK_CUR(fop_fd, offset);
}
/**
* lws_plat_file_read() - read from file
*
- * \param wsi: connection opened by
- * \param fd: file descriptor
+ * \param fop_fd: file handle
* \param amount: how much to read (rewritten by call)
* \param buf: buffer to write to
* \param len: max length
*/
static LWS_INLINE int LWS_WARN_UNUSED_RESULT
-lws_plat_file_read(struct lws *wsi, lws_filefd_type fd, unsigned long *amount,
- unsigned char *buf, unsigned long len)
+lws_vfs_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
+ uint8_t *buf, lws_filepos_t len)
{
- return lws_get_fops(lws_get_context(wsi))->LWS_FOP_READ(wsi, fd,
- amount, buf, len);
+ return fop_fd->fops->LWS_FOP_READ(fop_fd, amount, buf, len);
}
/**
* lws_plat_file_write() - write from file
*
- * \param wsi: connection opened by
- * \param fd: file descriptor
+ * \param fop_fd: file handle
* \param amount: how much to write (rewritten by call)
* \param buf: buffer to read from
* \param len: max length
*/
static LWS_INLINE int LWS_WARN_UNUSED_RESULT
-lws_plat_file_write(struct lws *wsi, lws_filefd_type fd, unsigned long *amount,
- unsigned char *buf, unsigned long len)
+lws_vfs_file_write(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
+ uint8_t *buf, lws_filepos_t len)
{
- return lws_get_fops(lws_get_context(wsi))->LWS_FOP_WRITE(wsi, fd,
- amount, buf, 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