option(LWS_WITH_SQLITE3 "Require SQLITE3 support" OFF)
option(LWS_WITH_SMTP "Provide SMTP support" OFF)
option(LWS_WITH_ESP8266 "Build for ESP8266" OFF)
+option(LWS_WITH_ESP32 "Build for ESP32" OFF)
option(LWS_PLAT_OPTEE "Build for OPTEE" OFF)
option(LWS_WITH_NO_LOGS "Disable all logging from being compiled in" OFF)
option(LWS_STATIC_PIC "Build the static version of the library with position-independent code" OFF)
set(LWS_HAVE_GETIFADDRS 1)
endif()
+if (LWS_WITH_ESP32)
+ set(LWS_WITH_SHARED OFF)
+ set(LWS_WITH_SSL OFF)
+ set(LWS_WITH_ZLIB OFF)
+ # set(LWS_WITHOUT_CLIENT ON)
+ set(LWS_WITHOUT_TESTAPPS ON)
+ set(LWS_WITHOUT_EXTENSIONS ON)
+ set(LWS_WITH_PLUGINS OFF)
+ set(LWS_WITH_RANGES ON)
+ # this implies no pthreads in the lib
+ set(LWS_MAX_SMP 1)
+ set(LWS_HAVE_MALLOC 1)
+ set(LWS_HAVE_REALLOC 1)
+ set(LWS_HAVE_GETIFADDRS 1)
+endif()
+
if (WIN32)
# this implies no pthreads in the lib
list(APPEND SOURCES
lib/lws-plat-optee.c)
else()
- list(APPEND SOURCES
- lib/lws-plat-unix.c)
+ if (LWS_WITH_ESP32)
+ list(APPEND SOURCES
+ lib/lws-plat-esp32.c)
+ else()
+ list(APPEND SOURCES
+ lib/lws-plat-unix.c)
+ endif()
endif()
endif()
endif()
message(" LWS_STATIC_PIC = ${LWS_STATIC_PIC}")
message(" LWS_WITH_RANGES = ${LWS_WITH_RANGES}")
message(" LWS_PLAT_OPTEE = ${LWS_PLAT_OPTEE}")
+message(" LWS_WITH_ESP32 = ${LWS_WITH_ESP32}")
message("---------------------------------------------------------------------")
--- /dev/null
+menu "Libwebsockets"
+
+config LWS
+ bool "Enable Libwebsockets"
+ default n
+ help
+ Enable Libwebsockets Library
+
+endmenu
--- /dev/null
+COMPONENT_ADD_INCLUDEDIRS := ../../../../../../../../../$(COMPONENT_BUILD_DIR)/include-ext
+
+COMPONENT_OWNBUILDTARGET:= 1
+
+CROSS_PATH1:=$(shell which xtensa-esp32-elf-gcc )
+CROSS_PATH:= $(shell dirname $(CROSS_PATH1) )/..
+
+#-DLWS_USE_BORINGSSL=1 \
+# -DOPENSSL_ROOT_DIR="${PWD}/../../boringssl" \
+# -DOPENSSL_LIBRARIES="${PWD}/../../boringssl/build/ssl/libssl.a;${PWD}/../../boringssl/build/crypto/libcrypto.a" \
+# -DOPENSSL_INCLUDE_DIRS="${PWD}/../../boringssl/include" \
+
+.PHONY: build
+build:
+ cd $(COMPONENT_BUILD_DIR) ; \
+ echo "doing lws cmake" ; \
+ cmake $(COMPONENT_PATH) -DLWS_C_FLAGS="$(CFLAGS)" \
+ -DCROSS_PATH=$(CROSS_PATH) \
+ -DCOMPONENT_PATH=$(COMPONENT_PATH) \
+ -DCMAKE_TOOLCHAIN_FILE=$(COMPONENT_PATH)/cross-esp32.cmake \
+ -DCMAKE_BUILD_TYPE=RELEASE \
+ -DLWS_WITH_NO_LOGS=0 \
+ -DLWS_WITH_ESP32=1 ;\
+ mkdir -p $(COMPONENT_BUILD_DIR)/include-ext ; \
+ cp $(COMPONENT_PATH)/lib/libwebsockets.h \
+ $(COMPONENT_BUILD_DIR)/lws_config.h \
+ $(COMPONENT_BUILD_DIR)/include-ext ; \
+ make VERBOSE=1 && \
+ cp ${COMPONENT_BUILD_DIR}/lib/libwebsockets.a ${COMPONENT_BUILD_DIR}/liblibwebsockets.a
+
+clean: myclean
+
+myclean:
+ rm -rf ./build
+
+INCLUDES := $(INCLUDES) -I build/
+
--- /dev/null
+#
+# CMake Toolchain file for crosscompiling on ARM.
+#
+# This can be used when running cmake in the following way:
+# cd build/
+# cmake .. -DCMAKE_TOOLCHAIN_FILE=../cross-arm-linux-gnueabihf.cmake
+#
+
+# Target operating system name.
+set(CMAKE_SYSTEM_NAME Linux)
+
+# Name of C compiler.
+set(CMAKE_C_COMPILER "${CROSS_PATH}/bin/xtensa-esp32-elf-gcc")
+
+SET(CMAKE_C_FLAGS "-nostdlib -Wall -Werror -I${COMPONENT_PATH}/../lwip/include/lwip/posix -I${COMPONENT_PATH}/../lwip/include/lwip -I${COMPONENT_PATH}/../lwip/include/lwip/port -I${COMPONENT_PATH}/../esp32/include/ ${LWS_C_FLAGS} -I${COMPONENT_PATH}/../nvs_flash/test_nvs_host -I${COMPONENT_PATH}/../freertos/include -Os" CACHE STRING "" FORCE)
+
+# Where to look for the target environment. (More paths can be added here)
+set(CMAKE_FIND_ROOT_PATH "${CROSS_PATH}")
+
+# Adjust the default behavior of the FIND_XXX() commands:
+# search programs in the host environment only.
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+
+# Search headers and libraries in the target environment only.
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+
* inform every vhost that hasn't already done it, that
* his protocols are initializing
*/
-int
+LWS_VISIBLE int
lws_protocol_init(struct lws_context *context)
{
struct lws_vhost *vh = context->vhost_list;
lws_callback_http_dummy, /* callback */
0, /* per_session_data_size */
0, /* max frame size / rx buffer */
+ 0, NULL
},
/*
* the other protocols are provided by lws plugins
*/
- { NULL, NULL, 0, 0 } /* terminator */
+ { NULL, NULL, 0, 0, 0, NULL} /* terminator */
};
#ifdef LWS_PLAT_OPTEE
const struct lws_protocol_vhost_options *pvo;
#ifdef LWS_WITH_PLUGINS
struct lws_plugin *plugin = context->plugin_list;
+#endif
struct lws_protocols *lwsp;
int m, f = !info->pvo;
-#endif
#ifdef LWS_HAVE_GETENV
char *p;
#endif
else
vh->keepalive_timeout = 5;
-#ifdef LWS_WITH_PLUGINS
- if (plugin) {
- /*
- * give the vhost a unified list of protocols including the
- * ones that came from plugins
- */
- lwsp = lws_zalloc(sizeof(struct lws_protocols) *
- (vh->count_protocols +
- context->plugin_protocol_count + 1));
- if (!lwsp)
- return NULL;
+ /*
+ * give the vhost a unified list of protocols including the
+ * ones that came from plugins
+ */
+ lwsp = lws_zalloc(sizeof(struct lws_protocols) *
+ (vh->count_protocols +
+ context->plugin_protocol_count + 1));
+ if (!lwsp) {
+ lwsl_err("OOM\n");
+ return NULL;
+ }
- m = vh->count_protocols;
- memcpy(lwsp, info->protocols,
- sizeof(struct lws_protocols) * m);
+ m = vh->count_protocols;
+ memcpy(lwsp, info->protocols, sizeof(struct lws_protocols) * m);
- /* for compatibility, all protocols enabled on vhost if only
- * the default vhost exists. Otherwise only vhosts who ask
- * for a protocol get it enabled.
- */
+ /* for compatibility, all protocols enabled on vhost if only
+ * the default vhost exists. Otherwise only vhosts who ask
+ * for a protocol get it enabled.
+ */
- if (info->options & LWS_SERVER_OPTION_EXPLICIT_VHOSTS)
- f = 0;
+ if (info->options & LWS_SERVER_OPTION_EXPLICIT_VHOSTS)
+ f = 0;
+ (void)f;
+#ifdef LWS_WITH_PLUGINS
+ if (plugin) {
while (plugin) {
for (n = 0; n < plugin->caps.count_protocols; n++) {
}
plugin = plugin->list;
}
- vh->protocols = lwsp;
- } else
+ }
#endif
+
+ if (info->options & LWS_SERVER_OPTION_EXPLICIT_VHOSTS)
+ vh->protocols = lwsp;
+ else
vh->protocols = info->protocols;
vh->same_vh_protocol_list = (struct lws **)
goto bail;
if (lws_context_init_client_ssl(info, vh))
goto bail;
- if (lws_context_init_server(info, vh))
+ if (lws_context_init_server(info, vh)) {
+ lwsl_err("init server failed\n");
goto bail;
+ }
while (1) {
if (!(*vh1)) {
#else
lwsl_notice("IPV6 not compiled in\n");
#endif
-#ifndef LWS_PLAT_OPTEE
+#if !defined(LWS_PLAT_OPTEE) && !defined(LWS_PLAT_ESP32)
lws_feature_status_libev(info);
lws_feature_status_libuv(info);
#endif
read_ok:
/* Nothing more to do for now */
- lwsl_info("%s: read_ok, used %ld\n", __func__, buf - oldbuf);
+ lwsl_info("%s: read_ok, used %ld\n", __func__, (long)(buf - oldbuf));
return buf - oldbuf;
wsi->state != LWSS_CLIENT_UNCONNECTED &&
reason != LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY &&
!wsi->socket_is_permanently_unusable) {
- lwsl_info("%s: shutting down connection: %p (sock %d, state %d)\n", __func__, wsi, wsi->sock, wsi->state);
+ lwsl_info("%s: shutting down connection: %p (sock %d, state %d)\n", __func__, wsi, (int)(long)wsi->sock, wsi->state);
n = shutdown(wsi->sock, SHUT_WR);
if (n)
lwsl_debug("closing: shutdown (state %d) ret %d\n", wsi->state, LWS_ERRNO);
return NULL;
}
-#if LWS_POSIX
+#if LWS_POSIX && !defined(LWS_WITH_ESP32)
LWS_VISIBLE int
interface_to_sa(struct lws_vhost *vh, const char *ifname, struct sockaddr_in *addr, size_t addrlen)
{
ai.ai_family = PF_UNSPEC;
ai.ai_socktype = SOCK_STREAM;
ai.ai_flags = AI_CANONNAME;
-
+#if !defined(LWS_WITH_ESP32)
if (getnameinfo((struct sockaddr *)ads,
sizeof(struct sockaddr_in),
name, name_len, NULL, 0, 0))
return -1;
-
+#endif
if (!rip)
return 0;
return 0;
}
+LWS_VISIBLE LWS_EXTERN void
+lws_set_fops(struct lws_context *context, struct lws_plat_file_ops *fops)
+{
+ memcpy(&context->fops, fops, sizeof *fops);
+}
+
/**
* lws_now_secs() - seconds since 1970-1-1
*
} else
#endif
-#ifdef LWS_USE_IPV6
+#if defined(LWS_USE_IPV6) && !defined(LWS_WITH_ESP32)
if (LWS_IPV6_ENABLED(vhost)) {
v = (struct sockaddr *)&serv_addr6;
n = sizeof(struct sockaddr_in6);
bzero((char *) &serv_addr4, sizeof(serv_addr4));
serv_addr4.sin_addr.s_addr = INADDR_ANY;
serv_addr4.sin_family = AF_INET;
+#if !defined(LWS_WITH_ESP32)
if (iface &&
interface_to_sa(vhost, iface,
lwsl_err("Unable to find interface %s\n", iface);
return -1;
}
-
+#endif
serv_addr4.sin_port = htons(port);
} /* ipv4 */
#define LWS_INLINE inline
#define LWS_O_RDONLY O_RDONLY
-#if !defined(MBED_OPERATORS) && !defined(LWS_WITH_ESP8266) && !defined(OPTEE_TA)
+#if !defined(MBED_OPERATORS) && !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)
+#if defined(LWS_WITH_ESP32)
+#define LWS_INVALID_FILE NULL
+#else
#define LWS_INVALID_FILE NULL
#endif
+#endif
#if defined(__GNUC__)
}
#else
+#if defined(LWS_WITH_ESP32)
+
+typedef int lws_sockfd_type;
+typedef void * lws_filefd_type;
+#define lws_sockfd_valid(sfd) (sfd >= 0)
+struct pollfd {
+ lws_sockfd_type fd; /**< fd related to */
+ short events; /**< which POLL... events to respond to */
+ short revents; /**< which POLL... events occurred */
+};
+#define POLLIN 0x0001
+#define POLLPRI 0x0002
+#define POLLOUT 0x0004
+#define POLLERR 0x0008
+#define POLLHUP 0x0010
+#define POLLNVAL 0x0020
+
+#include "freertos/timers.h"
+
+#if !defined(CONFIG_FREERTOS_HZ)
+#define CONFIG_FREERTOS_HZ 100
+#endif
+
+typedef TimerHandle_t uv_timer_t;
+typedef void uv_cb_t(uv_timer_t *);
+typedef void * uv_handle_t;
+
+struct timer_mapping {
+ uv_cb_t *cb;
+ uv_timer_t *t;
+};
+
+#define UV_VERSION_MAJOR 1
+
+#define lws_uv_getloop(a, b) (NULL)
+
+static inline void uv_timer_init(void *l, uv_timer_t *t)
+{
+ (void)l;
+ *t = NULL;
+}
+
+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));
+
+ if (!tm)
+ return;
+
+ tm->t = t;
+ tm->cb = cb;
+
+ *t = xTimerCreate("x", pdMS_TO_TICKS(first), !!rep, tm,
+ (TimerCallbackFunction_t)esp32_uvtimer_cb);
+ xTimerStart(*t, 0);
+}
+
+static inline void uv_timer_stop(uv_timer_t *t)
+{
+ xTimerStop(*t, 0);
+}
+
+static inline void uv_close(uv_handle_t *h, void *v)
+{
+ free(pvTimerGetTimerID((uv_timer_t)h));
+ xTimerDelete(*(uv_timer_t *)h, 0);
+}
+
+
+
+
+#else
typedef int lws_sockfd_type;
typedef int lws_filefd_type;
#define lws_sockfd_valid(sfd) (sfd >= 0)
#define LWS_POLLIN (POLLIN)
#define LWS_POLLOUT (POLLOUT)
#endif
+#endif
/** struct lws_pollargs - argument structure for all external poll related calls
* passed in via 'in' */
LWS_VISIBLE LWS_EXTERN int
lws_finalize_startup(struct lws_context *context);
+LWS_VISIBLE LWS_EXTERN int
+lws_protocol_init(struct lws_context *context);
+
#ifdef LWS_WITH_PLUGINS
/* PLUGINS implies LIBUV */
*/
LWS_VISIBLE LWS_EXTERN const char *
lws_get_peer_simple(struct lws *wsi, char *name, int namelen);
-#ifndef LWS_WITH_ESP8266
+#if !defined(LWS_WITH_ESP8266) && !defined(LWS_WITH_ESP32)
/**
* lws_interface_to_sa() - Convert interface name or IP to sockaddr struct
*
* library and in the user code.
*/
+#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
+#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
+#endif
#define LWS_FOP_FLAGS_MASK ((1 << 23) - 1)
#define LWS_FOP_FLAG_COMPR_ACCEPTABLE_GZIP (1 << 24)
*/
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_plat_file_open() - file open operations
*
--- /dev/null
+#include "private-libwebsockets.h"
+#include "freertos/timers.h"
+
+/*
+ * included from libwebsockets.c for unix builds
+ */
+
+unsigned long long time_in_microseconds(void)
+{
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return ((unsigned long long)tv.tv_sec * 1000000LL) + tv.tv_usec;
+}
+
+LWS_VISIBLE int
+lws_get_random(struct lws_context *context, void *buf, int len)
+{
+ // !!!
+ return 0;
+}
+
+LWS_VISIBLE int
+lws_send_pipe_choked(struct lws *wsi)
+{
+ fd_set writefds;
+ struct timeval tv = { 0, 0 };
+
+ /* treat the fact we got a truncated send pending as if we're choked */
+ if (wsi->trunc_len)
+ return 1;
+
+ FD_ZERO(&writefds);
+ FD_SET(wsi->sock, &writefds);
+
+ if (select(wsi->sock + 1, NULL, &writefds, NULL, &tv) < 1)
+ return 1;
+
+ return 0;
+}
+
+LWS_VISIBLE int
+lws_poll_listen_fd(struct lws_pollfd *fd)
+{
+ fd_set readfds;
+ struct timeval tv = { 0, 0 };
+
+ FD_ZERO(&readfds);
+ FD_SET(fd->fd, &readfds);
+
+ return select(fd->fd + 1, &readfds, NULL, NULL, &tv);
+}
+
+LWS_VISIBLE void
+lws_cancel_service_pt(struct lws *wsi)
+{
+}
+
+LWS_VISIBLE void
+lws_cancel_service(struct lws_context *context)
+{
+}
+
+LWS_VISIBLE void lwsl_emit_syslog(int level, const char *line)
+{
+ printf("%d: %s", level, line);
+}
+
+LWS_VISIBLE LWS_EXTERN int
+_lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
+{
+ struct lws_context_per_thread *pt;
+ int n = -1, m, c;
+
+ /* stay dead once we are dead */
+
+ if (!context || !context->vhost_list)
+ return 1;
+
+ pt = &context->pt[tsi];
+
+ if (timeout_ms < 0)
+ goto faked_service;
+
+ if (!context->service_tid_detected) {
+ struct lws _lws;
+
+ memset(&_lws, 0, sizeof(_lws));
+ _lws.context = context;
+
+ context->service_tid_detected =
+ context->vhost_list->protocols[0].callback(
+ &_lws, LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0);
+ }
+ context->service_tid = context->service_tid_detected;
+
+ /*
+ * is there anybody with pending stuff that needs service forcing?
+ */
+ if (!lws_service_adjust_timeout(context, 1, tsi)) {
+ /* -1 timeout means just do forced service */
+ _lws_plat_service_tsi(context, -1, pt->tid);
+ /* still somebody left who wants forced service? */
+ if (!lws_service_adjust_timeout(context, 1, pt->tid))
+ /* yes... come back again quickly */
+ timeout_ms = 0;
+ }
+
+// n = poll(pt->fds, pt->fds_count, timeout_ms);
+ {
+ fd_set readfds, writefds, errfds;
+ struct timeval tv = { timeout_ms / 1000,
+ (timeout_ms % 1000) * 1000 };
+ int max_fd = 0;
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ FD_ZERO(&errfds);
+
+ for (n = 0; n < pt->fds_count; n++) {
+ pt->fds[n].revents = 0;
+ if (pt->fds[n].fd >= max_fd)
+ max_fd = pt->fds[n].fd;
+ if (pt->fds[n].events & LWS_POLLIN)
+ FD_SET(pt->fds[n].fd, &readfds);
+ if (pt->fds[n].events & LWS_POLLOUT)
+ FD_SET(pt->fds[n].fd, &writefds);
+ FD_SET(pt->fds[n].fd, &errfds);
+ }
+
+ n = select(max_fd + 1, &readfds, &writefds, &errfds, &tv);
+ for (n = 0; n < pt->fds_count; n++) {
+ if (FD_ISSET(pt->fds[n].fd, &readfds))
+ pt->fds[n].revents |= LWS_POLLIN;
+ if (FD_ISSET(pt->fds[n].fd, &writefds))
+ pt->fds[n].revents |= LWS_POLLOUT;
+ if (FD_ISSET(pt->fds[n].fd, &errfds))
+ pt->fds[n].revents |= LWS_POLLHUP;
+ }
+ }
+
+
+#ifdef LWS_OPENSSL_SUPPORT
+ if (!pt->rx_draining_ext_list &&
+ !lws_ssl_anybody_has_buffered_read_tsi(context, tsi) && !n) {
+#else
+ if (!pt->rx_draining_ext_list && !n) /* poll timeout */ {
+#endif
+ lws_service_fd_tsi(context, NULL, tsi);
+ return 0;
+ }
+
+faked_service:
+ m = lws_service_flag_pending(context, tsi);
+ if (m)
+ c = -1; /* unknown limit */
+ else
+ if (n < 0) {
+ if (LWS_ERRNO != LWS_EINTR)
+ return -1;
+ return 0;
+ } else
+ c = n;
+
+ /* any socket with events to service? */
+ for (n = 0; n < pt->fds_count && c; n++) {
+ if (!pt->fds[n].revents)
+ continue;
+
+ c--;
+
+ m = lws_service_fd_tsi(context, &pt->fds[n], tsi);
+ if (m < 0)
+ return -1;
+ /* if something closed, retry this slot */
+ if (m)
+ n--;
+ }
+
+ return 0;
+}
+
+LWS_VISIBLE int
+lws_plat_check_connection_error(struct lws *wsi)
+{
+ return 0;
+}
+
+LWS_VISIBLE int
+lws_plat_service(struct lws_context *context, int timeout_ms)
+{
+ return _lws_plat_service_tsi(context, timeout_ms, 0);
+}
+
+LWS_VISIBLE int
+lws_plat_set_socket_options(struct lws_vhost *vhost, int fd)
+{
+ int optval = 1;
+ socklen_t optlen = sizeof(optval);
+
+#if defined(__APPLE__) || \
+ defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
+ defined(__NetBSD__) || \
+ defined(__OpenBSD__)
+ struct protoent *tcp_proto;
+#endif
+
+ if (vhost->ka_time) {
+ /* enable keepalive on this socket */
+ optval = 1;
+ if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
+ (const void *)&optval, optlen) < 0)
+ return 1;
+
+#if defined(__APPLE__) || \
+ defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
+ defined(__NetBSD__) || \
+ defined(__CYGWIN__) || defined(__OpenBSD__) || defined (__sun)
+
+ /*
+ * didn't find a way to set these per-socket, need to
+ * tune kernel systemwide values
+ */
+#else
+ /* set the keepalive conditions we want on it too */
+ optval = vhost->ka_time;
+ if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE,
+ (const void *)&optval, optlen) < 0)
+ return 1;
+
+ optval = vhost->ka_interval;
+ if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL,
+ (const void *)&optval, optlen) < 0)
+ return 1;
+
+ optval = vhost->ka_probes;
+ if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT,
+ (const void *)&optval, optlen) < 0)
+ return 1;
+#endif
+ }
+#if 0
+ /* Disable Nagle */
+ optval = 1;
+// if (setsockopt(fd, SOL_TCP, TCP_NODELAY, (const void *)&optval, optlen) < 0)
+// return 1;
+ tcp_proto = getprotobyname("TCP");
+ if (setsockopt(fd, tcp_proto->p_proto, TCP_NODELAY, &optval, optlen) < 0)
+ return 1;
+#endif
+ /* We are nonblocking... */
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
+ return 1;
+
+ return 0;
+}
+
+LWS_VISIBLE void
+lws_plat_drop_app_privileges(struct lws_context_creation_info *info)
+{
+}
+
+LWS_VISIBLE int
+lws_plat_context_early_init(void)
+{
+ //signal(SIGPIPE, SIG_IGN);
+
+// signal(SIGABRT, sigabrt_handler);
+
+ return 0;
+}
+
+LWS_VISIBLE void
+lws_plat_context_early_destroy(struct lws_context *context)
+{
+}
+
+LWS_VISIBLE void
+lws_plat_context_late_destroy(struct lws_context *context)
+{
+#ifdef LWS_WITH_PLUGINS
+ if (context->plugin_list)
+ lws_plat_plugins_destroy(context);
+#endif
+
+ if (context->lws_lookup)
+ lws_free(context->lws_lookup);
+}
+
+/* cast a struct sockaddr_in6 * into addr for ipv6 */
+
+LWS_VISIBLE int
+lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr,
+ size_t addrlen)
+{
+#if 0
+ int rc = -1;
+
+ struct ifaddrs *ifr;
+ struct ifaddrs *ifc;
+#ifdef LWS_USE_IPV6
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
+#endif
+
+ getifaddrs(&ifr);
+ for (ifc = ifr; ifc != NULL && rc; ifc = ifc->ifa_next) {
+ if (!ifc->ifa_addr)
+ continue;
+
+ lwsl_info(" interface %s vs %s\n", ifc->ifa_name, ifname);
+
+ if (strcmp(ifc->ifa_name, ifname))
+ continue;
+
+ switch (ifc->ifa_addr->sa_family) {
+ case AF_INET:
+#ifdef LWS_USE_IPV6
+ if (ipv6) {
+ /* map IPv4 to IPv6 */
+ bzero((char *)&addr6->sin6_addr,
+ sizeof(struct in6_addr));
+ addr6->sin6_addr.s6_addr[10] = 0xff;
+ addr6->sin6_addr.s6_addr[11] = 0xff;
+ memcpy(&addr6->sin6_addr.s6_addr[12],
+ &((struct sockaddr_in *)ifc->ifa_addr)->sin_addr,
+ sizeof(struct in_addr));
+ } else
+#endif
+ memcpy(addr,
+ (struct sockaddr_in *)ifc->ifa_addr,
+ sizeof(struct sockaddr_in));
+ break;
+#ifdef LWS_USE_IPV6
+ case AF_INET6:
+ memcpy(&addr6->sin6_addr,
+ &((struct sockaddr_in6 *)ifc->ifa_addr)->sin6_addr,
+ sizeof(struct in6_addr));
+ break;
+#endif
+ default:
+ continue;
+ }
+ rc = 0;
+ }
+
+ freeifaddrs(ifr);
+
+ if (rc == -1) {
+ /* check if bind to IP address */
+#ifdef LWS_USE_IPV6
+ if (inet_pton(AF_INET6, ifname, &addr6->sin6_addr) == 1)
+ rc = 0;
+ else
+#endif
+ if (inet_pton(AF_INET, ifname, &addr->sin_addr) == 1)
+ rc = 0;
+ }
+
+ return rc;
+#endif
+
+ return -1;
+}
+
+LWS_VISIBLE void
+lws_plat_insert_socket_into_fds(struct lws_context *context, struct lws *wsi)
+{
+ struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
+
+ pt->fds[pt->fds_count++].revents = 0;
+}
+
+LWS_VISIBLE void
+lws_plat_delete_socket_from_fds(struct lws_context *context,
+ struct lws *wsi, int m)
+{
+ struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
+
+ pt->fds_count--;
+}
+
+LWS_VISIBLE void
+lws_plat_service_periodic(struct lws_context *context)
+{
+}
+
+LWS_VISIBLE int
+lws_plat_change_pollfd(struct lws_context *context,
+ struct lws *wsi, struct lws_pollfd *pfd)
+{
+ return 0;
+}
+
+LWS_VISIBLE const char *
+lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt)
+{
+ return inet_ntop(af, src, dst, cnt);
+}
+
+static lws_filefd_type
+_lws_plat_file_open(struct lws *wsi, const char *filename,
+ unsigned long *filelen, int *flags)
+{
+ struct stat stat_buf;
+
+ int ret = open(filename, *flags, 0664);
+
+ if (ret < 0)
+ return LWS_INVALID_FILE;
+
+ if (fstat(ret, &stat_buf) < 0) {
+ close(ret);
+ return LWS_INVALID_FILE;
+ }
+ *filelen = stat_buf.st_size;
+ return (lws_filefd_type)ret;
+}
+
+static int
+_lws_plat_file_close(struct lws *wsi, lws_filefd_type fd)
+{
+ return close((int)fd);
+}
+
+unsigned long
+_lws_plat_file_seek_cur(struct lws *wsi, lws_filefd_type fd, long offset)
+{
+ return lseek((int)fd, offset, SEEK_CUR);
+}
+
+static int
+_lws_plat_file_read(struct lws *wsi, lws_filefd_type fd, unsigned long *amount,
+ unsigned char *buf, unsigned long len)
+{
+ long n;
+
+ n = read((int)fd, buf, len);
+ if (n == -1) {
+ *amount = 0;
+ return -1;
+ }
+
+ *amount = n;
+
+ return 0;
+}
+
+static int
+_lws_plat_file_write(struct lws *wsi, lws_filefd_type fd, unsigned long *amount,
+ unsigned char *buf, unsigned long len)
+{
+ long n;
+
+ n = write((int)fd, buf, len);
+ if (n == -1) {
+ *amount = 0;
+ return -1;
+ }
+
+ *amount = n;
+
+ return 0;
+}
+
+
+LWS_VISIBLE int
+lws_plat_init(struct lws_context *context,
+ struct lws_context_creation_info *info)
+{
+ /* master context has the global fd lookup array */
+ context->lws_lookup = lws_zalloc(sizeof(struct lws *) *
+ context->max_fds);
+ if (context->lws_lookup == NULL) {
+ lwsl_err("OOM on lws_lookup array for %d connections\n",
+ context->max_fds);
+ return 1;
+ }
+
+ lwsl_notice(" mem: platform fd map: %5lu bytes\n",
+ (unsigned long)(sizeof(struct lws *) * context->max_fds));
+
+ context->fops.LWS_FOP_OPEN = _lws_plat_file_open;
+ context->fops.LWS_FOP_CLOSE = _lws_plat_file_close;
+ context->fops.LWS_FOP_SEEK_CUR = _lws_plat_file_seek_cur;
+ context->fops.LWS_FOP_READ = _lws_plat_file_read;
+ context->fops.LWS_FOP_WRITE = _lws_plat_file_write;
+
+#ifdef LWS_WITH_PLUGINS
+ if (info->plugin_dirs)
+ lws_plat_plugins_init(context, info->plugin_dirs);
+#endif
+
+ return 0;
+}
+
+
+LWS_VISIBLE void esp32_uvtimer_cb(TimerHandle_t t)
+{
+ struct timer_mapping *p = pvTimerGetTimerID(t);
+
+ p->cb(p->t);
+}
+
* Newly truncated send. Buffer the remainder (it will get
* first priority next time the socket is writable)
*/
- lwsl_notice("%p new partial sent %d from %lu total\n", wsi, n,
+ lwsl_info("%p new partial sent %d from %lu total\n", wsi, n,
(unsigned long)real_len);
/*
if (LWS_ERRNO == LWS_EAGAIN ||
LWS_ERRNO == LWS_EWOULDBLOCK ||
LWS_ERRNO == LWS_EINTR) {
- if (LWS_ERRNO == LWS_EWOULDBLOCK)
+ if (LWS_ERRNO == LWS_EWOULDBLOCK) {
lws_set_blocking_send(wsi);
+ }
return LWS_SSL_CAPABLE_MORE_SERVICE;
}
* weren't able to deliver it right now
*/
if (pt->ah_count_in_use == context->max_http_header_pool) {
- lwsl_notice("%s: adding %p to ah waiting list\n", __func__, wsi);
+ lwsl_info("%s: adding %p to ah waiting list\n", __func__, wsi);
wsi->u.hdr.ah_wait_list = pt->ah_wait_list;
pt->ah_wait_list = wsi;
pt->ah_wait_list_length++;
if (protocol < vhost->protocols ||
protocol >= (vhost->protocols + vhost->count_protocols)) {
- lwsl_err("%s: protocol is not from vhost\n", __func__);
+
+ lwsl_err("%s: protocol %p is not from vhost %p (%p - %p)\n",
+ __func__, protocol, vhost->protocols, vhost,
+ (vhost->protocols + vhost->count_protocols));
return -1;
}
#include <ctype.h>
#include <limits.h>
#include <stdarg.h>
+
+#if defined(LWS_WITH_ESP32)
+#define MSG_NOSIGNAL 0
+#define SOMAXCONN 3
+#endif
+
#if defined(LWS_WITH_ESP8266)
#include <user_interface.h>
#define assert(n)
#if defined(LWS_BUILTIN_GETIFADDRS)
#include <getifaddrs.h>
#else
- #if !defined(LWS_WITH_ESP8266)
+ #if !defined(LWS_WITH_ESP8266) && !defined(LWS_WITH_ESP32)
#include <ifaddrs.h>
#endif
#endif
#elif defined (__sun)
#include <syslog.h>
#else
-#if !defined(LWS_WITH_ESP8266)
+#if !defined(LWS_WITH_ESP8266) && !defined(LWS_WITH_ESP32)
#include <sys/syslog.h>
#endif
#endif
#include <netdb.h>
-#if !defined(LWS_WITH_ESP8266)
+#if !defined(LWS_WITH_ESP8266) && !defined(LWS_WITH_ESP32)
#include <sys/mman.h>
#include <sys/un.h>
#include <netinet/in.h>
#define lws_libev_run(_a, _b) ((void) 0)
#define lws_libev_destroyloop(_a, _b) ((void) 0)
#define LWS_LIBEV_ENABLED(context) (0)
-#if LWS_POSIX
+#if LWS_POSIX && !defined(LWS_WITH_ESP32)
#define lws_feature_status_libev(_a) \
lwsl_notice("libev support not compiled in\n")
#else
#define lws_libuv_run(_a, _b) ((void) 0)
#define lws_libuv_destroyloop(_a, _b) ((void) 0)
#define LWS_LIBUV_ENABLED(context) (0)
-#if LWS_POSIX
+#if LWS_POSIX && !defined(LWS_WITH_ESP32)
#define lws_feature_status_libuv(_a) \
lwsl_notice("libuv support not compiled in\n")
#else
struct lws *wsi;
int m = 0;
+ (void)opt;
/* set up our external listening socket we serve on */
if (info->port == CONTEXT_PORT_NO_LISTEN || info->port == CONTEXT_PORT_NO_LISTEN_SERVER)
lwsl_err("ERROR opening socket\n");
return 1;
}
-
-#if LWS_POSIX
+#if LWS_POSIX && !defined(LWS_WITH_ESP32)
/*
* allow us to restart even if old sockets in TIME_WAIT
*/
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
(const void *)&opt, sizeof(opt)) < 0) {
+ lwsl_err("reuseaddr failed\n");
compatible_close(sockfd);
return 1;
}
const struct lws_protocol_vhost_options *pvo = m->interpret;
struct lws_process_html_args args;
const char *mimetype;
-#if !defined(_WIN32_WCE) && !defined(LWS_WITH_ESP8266)
+#if !defined(_WIN32_WCE) && !defined(LWS_WITH_ESP8266) && !defined(LWS_WITH_ESP32)
struct stat st;
int spin = 0;
#endif
char path[256], sym[512];
unsigned char *p = (unsigned char *)sym + 32 + LWS_PRE, *start = p;
unsigned char *end = p + sizeof(sym) - 32 - LWS_PRE;
-#if !defined(WIN32) && LWS_POSIX
+#if !defined(WIN32) && LWS_POSIX && !defined(LWS_WITH_ESP32)
size_t len;
#endif
int n;
lws_snprintf(path, sizeof(path) - 1, "%s/%s", origin, uri);
-#if !defined(_WIN32_WCE) && !defined(LWS_WITH_ESP8266)
+#if !defined(_WIN32_WCE) && !defined(LWS_WITH_ESP8266) && !defined(LWS_WITH_ESP32)
do {
spin++;
}
lwsl_debug(" %s mode %d\n", path, S_IFMT & st.st_mode);
-#if !defined(WIN32) && LWS_POSIX
+#if !defined(WIN32) && LWS_POSIX && !defined(LWS_WITH_ESP32)
if ((S_IFMT & st.st_mode) == S_IFLNK) {
len = readlink(path, sym, sizeof(sym) - 1);
if (len) {
}
wsi->u.ws.rx_ubuf_alloc = n;
lwsl_debug("Allocating RX buffer %d\n", n);
-#if LWS_POSIX
+#if LWS_POSIX && !defined(LWS_WITH_ESP32)
if (setsockopt(wsi->sock, SOL_SOCKET, SO_SNDBUF,
(const char *)&n, sizeof n)) {
lwsl_warn("Failed to set SNDBUF to %d", n);
}
new_wsi->tsi = n;
- lwsl_notice("Accepted wsi %p to context %p, tsi %d\n", new_wsi,
+ lwsl_debug("Accepted wsi %p to context %p, tsi %d\n", new_wsi,
vhost->context, new_wsi->tsi);
new_wsi->vhost = vhost;
return NULL;
}
- //lwsl_notice("%s: new wsi %p, sockfd %d, cb %p\n", __func__, new_wsi, accept_fd, context->vhost_list->protocols[0].callback);
+ lwsl_debug("%s: new wsi %p, sockfd %d, cb %p\n", __func__, new_wsi,
+ accept_fd, context->vhost_list->protocols[0].callback);
new_wsi->sock = accept_fd;
{
if (lws_check_opt(info->options, LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME))
return;
-#if LWS_POSIX
+#if LWS_POSIX && !defined(LWS_WITH_ESP32)
/* find canonical hostname */
gethostname((char *)context->canonical_hostname,
sizeof(context->canonical_hostname) - 1);
lws_plat_service_periodic(context);
/* retire unused deprecated context */
-#ifndef LWS_PLAT_OPTEE
+#if !defined(LWS_PLAT_OPTEE) && !defined(LWS_WITH_ESP32)
#if LWS_POSIX && !defined(_WIN32)
if (context->deprecated && !context->count_wsi_allocated) {
lwsl_notice("%s: ending deprecated context\n", __func__);
#cmakedefine LWS_USE_MBEDTLS
#cmakedefine LWS_USE_POLARSSL
#cmakedefine LWS_WITH_ESP8266
+#cmakedefine LWS_WITH_ESP32
#cmakedefine LWS_WITH_PLUGINS
#cmakedefine LWS_WITH_NO_LOGS