ESP32 platform
authorAndy Green <andy@warmcat.com>
Sat, 18 Feb 2017 09:26:40 +0000 (17:26 +0800)
committerAndy Green <andy@warmcat.com>
Sat, 18 Feb 2017 09:27:22 +0000 (17:27 +0800)
This is enough for all the test app features to work on ESP32 without
SSL.

16 files changed:
CMakeLists.txt
Kconfig [new file with mode: 0644]
component.mk [new file with mode: 0644]
cross-esp32.cmake [new file with mode: 0644]
lib/context.c
lib/handshake.c
lib/libwebsockets.c
lib/libwebsockets.h
lib/lws-plat-esp32.c [new file with mode: 0644]
lib/output.c
lib/parsers.c
lib/pollfd.c
lib/private-libwebsockets.h
lib/server.c
lib/service.c
lws_config.h.in

index d6de2e5..4fd9fc6 100644 (file)
@@ -109,6 +109,7 @@ option(LWS_WITH_GENERIC_SESSIONS "With the Generic Sessions plugin" OFF)
 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)
@@ -176,6 +177,22 @@ if (LWS_WITH_ESP8266)
  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
@@ -609,8 +626,13 @@ else()
                                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()
@@ -1657,6 +1679,7 @@ message(" LWS_WITH_GENERIC_SESSIONS = ${LWS_WITH_GENERIC_SESSIONS}")
 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("---------------------------------------------------------------------")
 
diff --git a/Kconfig b/Kconfig
new file mode 100644 (file)
index 0000000..7d62343
--- /dev/null
+++ b/Kconfig
@@ -0,0 +1,9 @@
+menu "Libwebsockets"
+
+config LWS
+    bool "Enable Libwebsockets"
+    default n
+    help
+       Enable Libwebsockets Library
+
+endmenu
diff --git a/component.mk b/component.mk
new file mode 100644 (file)
index 0000000..9b7edd1
--- /dev/null
@@ -0,0 +1,37 @@
+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/ 
+
diff --git a/cross-esp32.cmake b/cross-esp32.cmake
new file mode 100644 (file)
index 0000000..2dc0a10
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# 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)
+
index 829abdf..c72f473 100644 (file)
@@ -126,7 +126,7 @@ lws_vhost_protocol_options(struct lws_vhost *vh, const char *name)
  * 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;
@@ -301,11 +301,12 @@ static const struct lws_protocols protocols_dummy[] = {
                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
@@ -322,9 +323,9 @@ lws_create_vhost(struct lws_context *context,
        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
@@ -356,29 +357,31 @@ lws_create_vhost(struct lws_context *context,
        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++) {
@@ -397,9 +400,12 @@ lws_create_vhost(struct lws_context *context,
                        }
                        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 **)
@@ -522,8 +528,10 @@ lws_create_vhost(struct lws_context *context,
                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)) {
@@ -583,7 +591,7 @@ lws_create_context(struct lws_context_creation_info *info)
 #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
index cf7e44e..68215cb 100644 (file)
@@ -245,7 +245,7 @@ postbody_completion:
 
 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;
 
index 63374d0..211c586 100755 (executable)
@@ -428,7 +428,7 @@ just_kill_connection:
            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);
@@ -638,7 +638,7 @@ lws_get_urlarg_by_name(struct lws *wsi, const char *name, char *buf, int len)
        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)
 {
@@ -692,12 +692,12 @@ lws_get_addresses(struct lws_vhost *vh, void *ads, char *name,
                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;
 
@@ -928,6 +928,12 @@ lws_callback_vhost_protocols(struct lws *wsi, int reason, void *in, int len)
        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
  *
@@ -1580,7 +1586,7 @@ lws_socket_bind(struct lws_vhost *vhost, lws_sockfd_type sockfd, int port,
 
        } 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);
@@ -1634,6 +1640,7 @@ lws_socket_bind(struct lws_vhost *vhost, lws_sockfd_type sockfd, int port,
                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,
@@ -1641,7 +1648,7 @@ lws_socket_bind(struct lws_vhost *vhost, lws_sockfd_type sockfd, int port,
                        lwsl_err("Unable to find interface %s\n", iface);
                        return -1;
                }
-
+#endif
                serv_addr4.sin_port = htons(port);
        } /* ipv4 */
 
index ed55bd7..536eecd 100644 (file)
@@ -167,14 +167,18 @@ struct sockaddr_in;
 #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__)
 
@@ -533,6 +537,80 @@ static inline void uv_timer_stop(uv_timer_t *t)
 }
 
 #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)
@@ -544,6 +622,7 @@ typedef int lws_filefd_type;
 #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' */
@@ -1430,6 +1509,9 @@ lws_protocol_vh_priv_get(struct lws_vhost *vhost, const struct lws_protocols *pr
 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 */
@@ -3785,7 +3867,7 @@ lws_get_peer_addresses(struct lws *wsi, lws_sockfd_type fd, char *name,
  */
 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
  *
@@ -4175,11 +4257,20 @@ lws_cgi_kill(struct lws *wsi);
  * 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)
@@ -4221,7 +4312,8 @@ struct lws_plat_file_ops {
  */
 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
  *
diff --git a/lib/lws-plat-esp32.c b/lib/lws-plat-esp32.c
new file mode 100644 (file)
index 0000000..f9fb92d
--- /dev/null
@@ -0,0 +1,501 @@
+#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);
+}
+
index 5136d6e..a37225a 100644 (file)
@@ -198,7 +198,7 @@ handle_truncated_send:
         * 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);
 
        /*
@@ -775,8 +775,9 @@ lws_ssl_capable_write_no_ssl(struct lws *wsi, unsigned char *buf, int 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;
        }
index 14cbbd9..a1b8c82 100644 (file)
@@ -156,7 +156,7 @@ lws_header_table_attach(struct lws *wsi, int autoservice)
         * 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++;
index f68b72a..f829a8f 100644 (file)
@@ -414,7 +414,10 @@ lws_callback_on_writable_all_protocol_vhost(const struct lws_vhost *vhost,
 
        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;
        }
index 1f365eb..e9507c5 100644 (file)
 #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)
@@ -173,7 +179,7 @@ int kill(int pid, int sig);
 #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
@@ -183,12 +189,12 @@ int kill(int pid, int sig);
 #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>
@@ -972,7 +978,7 @@ LWS_EXTERN void lws_feature_status_libev(struct lws_context_creation_info *info)
 #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
@@ -1002,7 +1008,7 @@ LWS_EXTERN void lws_feature_status_libuv(struct lws_context_creation_info *info)
 #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
index 1da1529..d4d92ca 100644 (file)
@@ -42,6 +42,7 @@ lws_context_init_server(struct lws_context_creation_info *info,
        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)
@@ -95,13 +96,13 @@ lws_context_init_server(struct lws_context_creation_info *info,
                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;
        }
@@ -325,21 +326,21 @@ lws_http_serve(struct lws *wsi, char *uri, const char *origin,
        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++;
 
@@ -349,7 +350,7 @@ lws_http_serve(struct lws *wsi, char *uri, const char *origin,
                }
 
                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) {
@@ -1494,7 +1495,7 @@ upgrade_ws:
                }
                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);
@@ -1577,7 +1578,7 @@ lws_create_new_server_wsi(struct lws_vhost *vhost)
        }
 
        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;
@@ -1690,7 +1691,8 @@ lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd)
                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;
 
@@ -2370,7 +2372,7 @@ lws_server_get_canonical_hostname(struct lws_context *context,
 {
        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);
index 0d4ec66..a5cbd0f 100644 (file)
@@ -711,7 +711,7 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, int t
                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__);
index b98a74a..2bb1a50 100644 (file)
@@ -20,6 +20,7 @@
 #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