canonical libwebsockets.org networking library

Overview

CI status Coverity Scan Build Status CII Best Practices Codacy Badge Total alerts Language grade: C/C++ Language grade: JavaScript

Libwebsockets

Libwebsockets is a simple-to-use, MIT-license, pure C library providing client and server for http/1, http/2, websockets, MQTT and other protocols in a security-minded, lightweight, configurable, scalable and flexible way. It's easy to build and cross-build via cmake and is suitable for tasks from embedded RTOS through mass cloud serving.

80 independent minimal examples for various scenarios, CC0-licensed (public domain) for cut-and-paste, allow you to get started quickly.

overview

News

Transition from master branch to main branch

"master" branch was just the default branch name from git originally, it was not selected for lws to have any semantic value in itself. There's no problem changing it to the more universally neutral "main" other than any explicit references spread around over the last 10 years to "master" breaking, which can be managed.

As a first step, I updated my push scripts, that keep libwebsockets.org git and the github mirror in sync, to push stuff on "master" also to "main" branch to establish it. If you currently refer to "master" branch in lws for build or CI, you should switch to using "main".

For the next months the two should run in parallel and I'll move over references to "master" in lws docs to use "main", eventually some point after the next release, master will be deleted.

In github, I changed its default branch for libwebsockets to "main", since main and master are updated in lockstep currently, this should hopefully have limited impact.

v4.1.0 and v4.1-stable are released

See the changelog, summary

  • NEW: travis / appveyor / bintray are replaced by Sai https://libwebsockets.org/sai/ which for lws currently does 167 builds per git push on 16 platforms, all self-hosted. The homebrew bash scripts used to select Minimal examples are replaced by CTest. Platforms currently include Fedora/AMD/GCC, Windows/AMD/mingw32, Windows/AMD/mingw64, Android/ aarch64/LLVM, esp-idf (on WROVER-KIT and HELTEC physical boards), Fedora/ RISCV (on QEMU)/GCC, CentOS8/AMD/GCC, Gentoo/AMD/GCC, Bionic/AMD/GCC, Linkit 7697, Focal/AMD/GCC, Windows (on QEMU)/AMD/MSVC, Focal/aarch64-RPI4/GCC, iOS/aarch64/LLVM and OSX/AMD/LLVM.

  • NEW: The single CMakeLists.txt has been refactored and modernized into smaller CMakeLists.txt in the subdirectory along with the code that is being managed for build by it. Build options are still listed in the top level as before but the new way is much more maintainable.

  • NEW: Captive Portal Detection. Lws can determine if the active default route is able to connect to the internet, or is in a captive portal type situation, by trying to connect to a remote server that will respond in an unusual way, like provide a 204.

  • NEW: Secure streams: Support system trust store if it exists Build on Windows Support lws raw socket protocol in SS Support Unix Domain Socket transport

  • NEW: Windows: Support Unix Domain Sockets same as other platforms

  • NEW: Windows: Build using native pthreads, async dns, ipv6 on MSVC

  • NEW: lws_struct: BLOB support

  • NEW: lws_sul: Now provides two sorted timer domains, a default one as before, and another whose scheduled events are capable to wake the system from suspend

  • NEW: System Message Distribution: lws_smd provides a very lightweight way to pass short messages between subsystems both in RTOS type case where the subsystems are all on the lws event loop, and in the case participants are in different processes, using Secure Streams proxying. Participants register a bitmap of message classes they care about; if no particpant cares about a particular message, it is rejected at allocation time for the sender, making it cheap to provide messages speculatively. See lib/system/smd/README.md for full details.

  • NEW: lws_drivers: wrappers for SDK driver abstractions (or actual drivers) See lib/drivers/README.md, example implementations minimal-examples/embedded/esp32/esp-wrover-kit - generic gpio - generic LED (by name) lib/drivers/led/README.md - generic PWM, sophisticated interpolated table sequencers with crossfade
    - generic button (by name), with debounce and press classification emitting rich SMD click, long-click, double-click, down, repeat, up JSON messages lib/drivers/button/README.md - bitbang i2c on generic gpio (hw support can use same abstract API) - bitbang spi on generic gpio (hw support can use same abstract API) - generic display object, can be wired up to controller drivers that hook up by generic i2c or spi, generic backlight PWM sequencing and blanking timer support - generic settings storage: get and set blobs by name - generic network device: netdev abstract class with WIFI / Ethernet implementations using underlying SDK APIs; generic 80211 Scan managements and credentials handling via lws_settings This is the new way to provide embedded platform functionality that was in the past done like esp32-factory. Unlike the old way, the new way has no native apis in it and can be built on other SDK / SoCs the same.

  • NEW: Security-aware JWS JWT (JSON Web Tokens) apis are provided on top of the existing JOSE / JWS apis. All the common algorithms are available along with some high level apis like lws http cookie -> JWT struct -> lws http cookie.

  • REMOVED: esp32-helper and friends used by esp32-factory now lws_drivers exists

  • REMOVED: generic sessions and friends now JWT is provided

v4.0 is released

Users wanting a stable branch should follow v4.0-stable to get the most stable version at any given time.

See the changelog for information on the huge amount of new features in this release, and additional information below.

 - NEW: Lws is now under the MIT license, see ./LICENSE for details
 
 - NEW: GLIB native event loop support, lws + gtk example

 - NEW: native lws MQTT client... supports client stream binding like h2 when
   multiple logical connections are going to the same endpoint over MQTT, they
   transparently and independently share the one connection + tls tunnel
 
 - NEW: "Secure Streams"... if you are making a device with client connections
   to the internet or cloud, this allows separation of the communications
   policy (endpoints, tls cert validation, protocols, etc) from the code, with
   the goal you can combine streams, change protocols and cloud provision, and
   reflect that in the device's JSON policy document without having to change
   any code.

 - NEW: lws_system: New lightweight and efficient Asynchronous DNS resolver
   implementation for both A and AAAA records, supports recursive (without
   recursion in code) lookups, caching, and getaddrinfo() compatible results
   scheme (from cache directly without per-consumer allocation).  Able to
   perform DNS lookups without introducing latency in the event loop.

 - NEW: lws_system: ntpclient implementation with interface for setting system
   time via lws_system ops
 
 - NEW: lws_system: dhcpclient implementation
 
 - NEW: Connection validity tracking, autoproduce PING/PONG for protocols that
   support it if not informed that the connection has passed data in both
   directions recently enough

 - NEW: lws_retry: standardized exponential backoff and retry timing based
   around backoff table and lws_sul

 - NEW: there are official public helpers for unaligned de/serialization of all
   common types, see eh, lws_ser_wu16be() in include/libwebsockets/lws-misc.h

 - NEW: lws_tls_client_vhost_extra_cert_mem() api allows attaching extra certs
   to a client vhost from DER in memory
   
 - NEW: lws_system: generic blobs support passing auth tokens, per-connection
   client certs etc from platform into lws

 - NEW: public helpers to consume and produce ipv4/6 addresses in a clean way,
   along with lws_sockaddr46 type now public.  See eg, lws_sockaddr46-based
   lws_sa46_parse_numeric_address(), lws_write_numeric_address()
   in include/libwebsockets/lws-network-helper.h

 - Improved client redirect handling, h2 compatibility
 
 - NEW: lwsac: additional features for constant folding support (strings that
   already are in the lwsac can be pointed to without copying again), backfill
   (look for gaps in previous chunks that could take a new use size), and
   lwsac_extend() so last use() can attempt to use more unallocated chunk space

 - NEW: lws_humanize: apis for reporting scalar quanties like 1234 as "1.234KB"
   with the scaled symbol strings passed in by caller

 - NEW: freertos: support lws_cancel_service() by using UDP pair bound to lo,
   since it doesn't have logical pipes

 - NEW: "esp32" plat, which implemented freertos plat compatibility on esp32, is
   renamed to "freertos" plat, targeting esp32 and other freertos platforms

 - NEW: base64 has an additional api supporting stateful decode, where the input
   is not all in the same place at the same time and can be processed
   incrementally

 - NEW: lws ws proxy: support RFC8441
   
 - NEW: lws_spawn_piped apis: generic support for vforking a process with child
   wsis attached to its stdin, stdout and stderr via pipes.  When processes are
   reaped, a specified callback is triggered.  Currently Linux + OSX.
   
 - NEW: lws_fsmount apis: Linux-only overlayfs mount and unmount management for
   aggregating read-only layers with disposable, changeable upper layer fs

 - Improvements for RTOS / small build case bring the footprint of lws v4 below
   that of v3.1 on ARM 
   
 - lws_tokenize: flag specifying # should mark rest of line as comment

 - NEW: minimal example for integrating libasound / alsa via raw file

 - lws_struct: sqlite and json / lejp translation now usable


Introducing Secure Streams client support

Secure Streams is an optional layer above lws (-DLWS_WITH_SECURE_STREAMS=1) that separates connectivity policy into a JSON document, which can be part of the firmware or fetched at boot time.

Code no longer deals with details like endpoint specification or tls cert stack used to validate the remote server, it's all specified in JSON, eg, see this example. Even the protocol to use to talk to the server, between h1, h2, ws or MQTT, is specified in the policy JSON and the code itself just deals with payloads and optionally metadata, making it possible to switch endpoints, update certs and even switch communication protocols by just editing the JSON policy and leaving the code alone.

Logical Secure Stream connections outlive any underlying lws connection, and support "nailed-up" connection reacquisition and exponential backoff management.

See ./lib/secure-streams/README.md and the related minimal examples for more details.

mqtt client support

If you enable -DLWS_ROLE_MQTT=1, lws can now support QoS0 and QoS1 MQTT client connections. See the examples at ./minimal-examples/mqtt-client

libglib native event loop support

glib's event loop joins libuv, libevent and libev support in lws for both the lws_context creating and owning the loop object for its lifetime, and for an already-existing "foreign loop" where the lws_context is created, attaches, detaches, and is destroyed without affecting the loop.

This allows direct, lock-free integration of lws functionality with, eg, a GTK app's existing GMainLoop / glib g_main_loop. Just select -DLWS_WITH_GLIB=1 at cmake time to enable. The -eventlib minimal examples also support --glib option to select using the glib loop at runtime.

There's also a gtk example that is built if lws cmake has -DLWS_WITH_GTK=1.

lws_system helper for attaching code to a single event loop from another thread

lws_system ops struct now has a member that enables other threads (in the same process) to request a callback they define from the lws event loop thread context as soon as possible. From here, in the event loop thread context, they can set up their lws functionality before returning and letting it operate wholly from the lws event loop. The original thread calling the api to request the callback returns immediately.

Improvements on tx credit

H2 clients and servers can now modulate RX flow control on streams precisely, ie, define the size of the first incoming data and hand out more tx credit at timing of its choosing to throttle or completely quench the remote server sending as it likes.

The only RFC-compatible way to acheive this is set the initial tx credit to 0 and set it explicitly when sending the headers... client code can elect to do this rather than automatically manage the credit by setting a new flag LCCSCF_H2_MANUAL_RXFLOW and indicating the initial tx credit for that stream in client connection info member manual_initial_tx_credit. A new public api lws_wsi_tx_credit() allows dynamic get and add to local and estimated remote peer credit for a connection. This api can be used without knowing if the underlying connection is h2 or not.

lws_system: DHCP client

DHCP client is now another network service that can be integrated into lws, with LWS_WITH_SYS_DHCP_CLIENT at CMake. When enabled, the lws_system state is held at DHCP until at least one registered network interface acquires a usable set of DHCP information including ip, subnet mask, router / gateway address and at least one DNS server.

See the api-test-dhcp Minimal Example for how to use.

UDP integration with lws_retry

UDP support in lws has new helper that allow lws_retry to be applied for retry, and the ability to synthesize rx and tx udp packetloss systemwide to confirm retry strategies. Since multiple transactions may be in flight on one UDP socket, the support relies on an lws_sul in the transaction object to manage the transaction retries individually.

See READMEs/README.udp.md for details.

lws_system: system state and notification handlers

Lws now has the concept of systemwide state held in the context... this is to manage that there may be multiple steps that need the network before it's possible for the user code to operate normally. The steps defined are

CONTEXT_CREATED, INITIALIZED, IFACE_COLDPLUG, DHCP, TIME_VALID, POLICY_VALID, REGISTERED, AUTH1, AUTH2, OPERATIONAL and POLICY_INVALID. OPERATIONAL is the state where user code can run normally.

User and other parts of lws can hook notifier callbacks to receive and be able to veto system state changes, either definitively or because they have been triggered to perform a step asynchronously and will move the state on themselves when it completes.

By default just after context creation, lws attempts to move straight to OPERATIONAL. If no notifier interecepts it, it will succeed to do that and operate in a backwards-compatible way. Enabling various features like lws ntpclient also enable notifiers that hold progress at the related state until their operation completes successfully, eg, not able to enter TIME_VALID until ntpclient has the time.

See READMEs/README.lws_system.md for details.

lws_system: HAL ops struct

Lws allows you to define a standardized ops struct at context creation time so your user code can get various information like device serial number without embedding system-specific code throughout the user code. It can also perform some generic functions like requesting a device reboot.

See READMEs/README.lws_system.md for details.

lws_system: ntpclient

Optional lws system service enabled by cmake -DLWS_WITH_SYS_NTPCLIENT intercepts the lws_system TIME_VALID state and performs ntpclient to get the date and time before entering TIME_VALID. This allows user code to validate tls certificates correctly knowing the current date and time by the time it reached OPERATIONAL.

Connection Validity tracking

Lws now allows you to apply a policy for how long a network connection may go without seeing something on it that confirms it's still valid in the sense of passing traffic cohernetly both ways. There's a global policy in the context which defaults to 5m before it produces a PING if possible, and 5m10 before the connection will be hung up, user code can override this in the context, vhost (for server) and client connection info (for client).

An api lws_validity_confirmed(wsi) is provided so user code can indicate that it observed traffic that must mean the connection is passing traffic in both directions to and from the peer. In the absence of these confirmations lws will generate PINGs and take PONGs as the indication of validity.

lws_system: Async DNS support

Master now provides optional Asynchronous (ie, nonblocking) recursive DNS resolving. Enable with -DLWS_WITH_SYS_ASYNC_DNS=1 at cmake. This provides a quite sophisticated ipv4 + ipv6 capable resolver that autodetects the dns server on several platforms and operates a UDP socket to its port 53 to produce and parse DNS packets from the event loop. And of course, it's extremely compact.

It broadly follows the getaddrinfo style api, but instead of creating the results on the heap for each caller, it caches a single result according to the TTL and then provides refcounted const pointers to the cached result to callers. While there are references on the cached result it can't be reaped.

See READMEs/README.async-dns.md for detailed information on how it works, along with api-tests/api-test-async-dns minimal example.

Detailed Latency

You can now opt to measure and store us-resolution statistics on effective latencies for client operations, and easily spool them to a file in a format suitable for gnuplot, or handle in your own callback. Enable -DLWS_WITH_DETAILED_LATENCY=1 in cmake to build it into lws. (NB 2021-01-12 this has been replaced by the lws_metrics support)

If you are concerned about operation latency or potential blocking from user code, or behaviour under load, or latency variability on specific platforms, you can get real numbers on your platform using this.

Timings for all aspects of events on connections are recorded, including the time needed for name resolution, setting up the connection, tls negotiation on both client and server sides, and each read and write.

See READMEs/README.detailed-latency.md for how to use it.

Client connection logic rewrite

Lws now makes much better use of the DNS results for ipv4 and ipv6... it will iterate through them automatically making the best use it can of what's provided and attempting new connections for each potentially usable one in turn before giving up on the whole client connection attempt.

If ipv6 is disabled at cmake it can only use A / ipv4 records, but if ipv6 is enabled, it tries both; if only ipv6 is enabled it promotes ipv4 to ::ffff:1.2.3.4 IPv4-in-IPv6 addresses.

New network helpers for ipv4 and ipv6

An internal union lws_sockaddr46 that combines struct sockaddr_in and struct sockaddr_in6 is now public, and there are helpers that can parse (using lws_tokenize) any valid numeric representation for ipv4 and ipv6 either into byte arrays and lengths, or directly to and from lws_sockaddr46.

h2 long poll support

Lws now supports the convention that half-closing an h2 http stream may make the stream 'immortal', in terms of not being bound by normal timeouts. For the client side, there's an api that can be applied to the client stream to make it transition to this "read-only" long poll mode.

See READMEs/README.h2-long-poll.md for full details, including how to test it with the minimal examples.

h1 client parser improvements

H1 is not so simple to parse because the header length is not known until it has been fully parsed. The next header, or http body may be directly coalesced with the header as well. Lws has supported bulk h1 parsing from a buffer for a long time, but on clientside due to interactions with http proxying it had been stuck parsing the header bytewise out of the tls buffer. Now, everything now bulk parses from a buffer and uses a buflist to pass leftovers through the event loop cleanly.

lws_sul time refactor

Just before v3.2 there was a big refactor about how lws handles time. It now explicitly schedules anything that may happen in the future on a single, sorted linked-list, at us resolution. When entering a poll wait (or returning to an event lib loop) it checks the interval between now and the earliest event on the list to figure out how long to wait if there are no network events. For the event loop case, it sets a native event lib timer to enforce it.

See READMEs/README.lws_sul.md for more details and a handy api where you can schedule your own arbitrary callbacks using this system.

Master is now MIT-licensed

Libwebsockets is now under the MIT license. See ./LICENSE.

Support

This is the libwebsockets C library for lightweight websocket clients and servers. For support, visit

https://libwebsockets.org

and consider joining the project mailing list at

https://libwebsockets.org/mailman/listinfo/libwebsockets

You can get the latest version of the library from git:

Doxygen API docs for development: https://libwebsockets.org/lws-api-doc-master/html/index.html

Comments
  • pipelined requests bug

    pipelined requests bug

    if pipelined requests are sent in glued chunk larger than 2048 bytes then connection is stopped processing and warning "Duplicated method" is given

    opened by rickynelson1939 118
  • libuv backend

    libuv backend

    Hi guys.

    I took a nap and then I implemented a quick test with libuv. It just started working but seems pretty stable. I need to add more functionalities (signals) and clean things up.

    Would you be interested in working with me to add this new backend? It shares a lot with libev in terms of concepts so maybe it would be easiest to merge libev/libuv backends into one (with some differences, ofc). But this is completely up to you.

    This is my (really ugly) first patch version:

    diff --git a/lib/context.c b/lib/context.c
    index e4cbe78..20650cb 100644
    --- a/lib/context.c
    +++ b/lib/context.c
    @@ -378,9 +378,10 @@ lws_context_destroy(struct lws_context *context)
            }
        }
     #ifdef LWS_USE_LIBEV
    -   ev_io_stop(context->io_loop, &context->w_accept.watcher);
    -   if (context->use_ev_sigint)
    -       ev_signal_stop(context->io_loop, &context->w_sigint.watcher);
    +    uv_poll_stop(&context->w_accept.watcher);
    +    //ev_io_stop(context->io_loop, &context->w_accept.watcher);
    +    //if (context->use_ev_sigint)
    +        //ev_signal_stop(context->io_loop, &context->w_sigint.watcher);
     #endif /* LWS_USE_LIBEV */
    
        for (n = 0; n < context->count_threads; n++) {
    diff --git a/lib/libev.c b/lib/libev.c
    index 167c045..a7fd1cb 100644
    --- a/lib/libev.c
    +++ b/lib/libev.c
    @@ -30,24 +30,24 @@ void lws_feature_status_libev(struct lws_context_creation_info *info)
     }
    
     static void
    -lws_accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
    +lws_accept_cb(uv_poll_t *watcher, int status, int revents)
     {
        struct lws_io_watcher *lws_io = container_of(watcher,
                            struct lws_io_watcher, watcher);
        struct lws_context *context = lws_io->context;
        struct lws_pollfd eventfd;
    
    -   if (revents & EV_ERROR)
    -       return;
    +    if (status < 0/*revents & EV_ERROR*/)
    +        return;
    
    -   eventfd.fd = watcher->fd;
    +    eventfd.fd = watcher->io_watcher.fd;
        eventfd.events = 0;
    -   eventfd.revents = EV_NONE;
    -   if (revents & EV_READ) {
    +    eventfd.revents = 0;//EV_NONE;
    +    if (revents & UV_READABLE) {
            eventfd.events |= LWS_POLLIN;
            eventfd.revents |= LWS_POLLIN;
        }
    -   if (revents & EV_WRITE) {
    +    if (revents & UV_WRITABLE) {
            eventfd.events |= LWS_POLLOUT;
            eventfd.revents |= LWS_POLLOUT;
        }
    @@ -55,9 +55,9 @@ lws_accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
     }
    
     LWS_VISIBLE void
    -lws_sigint_cb(struct ev_loop *loop, struct ev_signal *watcher, int revents)
    +lws_sigint_cb(uv_loop_t *loop, uv_signal_t *watcher, int revents)
     {
    -   ev_break(loop, EVBREAK_ALL);
    +    //ev_break(loop, EVBREAK_ALL);
     }
    
     LWS_VISIBLE int
    @@ -74,17 +74,17 @@ lws_sigint_cfg(struct lws_context *context, int use_ev_sigint,
     }
    
     LWS_VISIBLE int
    -lws_initloop(struct lws_context *context, struct ev_loop *loop)
    +lws_initloop(struct lws_context *context, uv_loop_t *loop)
     {
    -   struct ev_signal *w_sigint = &context->w_sigint.watcher;
    -   struct ev_io *w_accept = &context->w_accept.watcher;
    -   const char * backend_name;
    +    //uv_signal_t *w_sigint = &context->w_sigint.watcher;
    +    uv_poll_t *w_accept = &context->w_accept.watcher;
    +    //const char * backend_name;
        int status = 0;
    -   int backend;
    -   int m = 0; /* !!! TODO add pt support */
    +    //int backend;
    +    int m = 0; /* !!! TODO add pt support */
    
        if (!loop)
    -       loop = ev_default_loop(0);
    +        loop = uv_default_loop();
    
        context->io_loop = loop;
    
    @@ -92,15 +92,17 @@ lws_initloop(struct lws_context *context, struct ev_loop *loop)
         * Initialize the accept w_accept with the listening socket
         * and register a callback for read operations
         */
    -   ev_io_init(w_accept, lws_accept_cb, context->pt[m].lserv_fd, EV_READ);
    -   ev_io_start(context->io_loop,w_accept);
    +    uv_poll_init(context->io_loop, w_accept, context->pt[m].lserv_fd);
    +    uv_poll_start(w_accept, UV_READABLE, lws_accept_cb);
    +    //ev_io_init(w_accept, lws_accept_cb, context->pt[m].lserv_fd, UV_READABLE);
    +    //ev_io_start(context->io_loop,w_accept);
    
        /* Register the signal watcher unless the user says not to */
        if (context->use_ev_sigint) {
    -       ev_signal_init(w_sigint, context->lws_ev_sigint_cb, SIGINT);
    -       ev_signal_start(context->io_loop,w_sigint);
    +        //ev_signal_init(w_sigint, context->lws_ev_sigint_cb, SIGINT);
    +        //ev_signal_start(context->io_loop,w_sigint);
        }
    -   backend = ev_backend(loop);
    +    /*backend = ev_backend(loop);
    
        switch (backend) {
        case EVBACKEND_SELECT:
    @@ -126,7 +128,7 @@ lws_initloop(struct lws_context *context, struct ev_loop *loop)
            break;
        }
    
    -   lwsl_notice(" libev backend: %s\n", backend_name);
    +    lwsl_notice(" libev backend: %s\n", backend_name);*/
    
        return status;
     }
    @@ -135,22 +137,24 @@ LWS_VISIBLE void
     lws_libev_accept(struct lws *new_wsi, int accept_fd)
     {
        struct lws_context *context = lws_get_context(new_wsi);
    -   struct ev_io *r = &new_wsi->w_read.watcher;
    -   struct ev_io *w = &new_wsi->w_write.watcher;
    +    uv_poll_t *r = &new_wsi->w_read.watcher;
    +    //uv_poll_t *w = &new_wsi->w_write.watcher;
    
        if (!LWS_LIBEV_ENABLED(context))
            return;
    
        new_wsi->w_read.context = context;
        new_wsi->w_write.context = context;
    -   ev_io_init(r, lws_accept_cb, accept_fd, EV_READ);
    -   ev_io_init(w, lws_accept_cb, accept_fd, EV_WRITE);
    +    uv_poll_init(context->io_loop, r, accept_fd);
    +    //ev_io_init(r, lws_accept_cb, accept_fd, UV_READABLE);
    +    //ev_io_init(w, lws_accept_cb, accept_fd, UV_WRITABLE);
     }
    
     LWS_VISIBLE void
     lws_libev_io(struct lws *wsi, int flags)
     {
        struct lws_context *context = lws_get_context(wsi);
    +    int current_events = wsi->w_read.watcher.io_watcher.pevents & (UV_READABLE | UV_WRITABLE);
    
        if (!LWS_LIBEV_ENABLED(context))
            return;
    @@ -162,15 +166,26 @@ lws_libev_io(struct lws *wsi, int flags)
               (flags & (LWS_EV_READ | LWS_EV_WRITE)));
    
        if (flags & LWS_EV_START) {
    -       if (flags & LWS_EV_WRITE)
    -           ev_io_start(context->io_loop, &wsi->w_write.watcher);
    -       if (flags & LWS_EV_READ)
    -           ev_io_start(context->io_loop, &wsi->w_read.watcher);
    +        if (flags & LWS_EV_WRITE)
    +            current_events |= UV_WRITABLE;
    +            //ev_io_start(context->io_loop, &wsi->w_write.watcher);
    +        if (flags & LWS_EV_READ)
    +            current_events |= UV_READABLE;
    +            //ev_io_start(context->io_loop, &wsi->w_read.watcher);
    +
    +        uv_poll_start(&wsi->w_read.watcher, current_events, lws_accept_cb);
        } else {
    -       if (flags & LWS_EV_WRITE)
    -           ev_io_stop(context->io_loop, &wsi->w_write.watcher);
    -       if (flags & LWS_EV_READ)
    -           ev_io_stop(context->io_loop, &wsi->w_read.watcher);
    +        if (flags & LWS_EV_WRITE)
    +            current_events &= ~UV_WRITABLE;
    +            //ev_io_stop(context->io_loop, &wsi->w_write.watcher);
    +        if (flags & LWS_EV_READ)
    +            current_events &= ~UV_READABLE;
    +            //ev_io_stop(context->io_loop, &wsi->w_read.watcher);
    +
    +        if (!(current_events & (UV_READABLE | UV_WRITABLE)))
    +            uv_poll_stop(&wsi->w_read.watcher);
    +        else
    +            uv_poll_start(&wsi->w_read.watcher, current_events, lws_accept_cb);
        }
     }
    
    @@ -190,5 +205,5 @@ LWS_VISIBLE void
     lws_libev_run(const struct lws_context *context)
     {
        if (context->io_loop && LWS_LIBEV_ENABLED(context))
    -       ev_run(context->io_loop, 0);
    +        uv_run(context->io_loop, 0);
     }
    diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h
    index 9b66352..400ab81 100644
    --- a/lib/libwebsockets.h
    +++ b/lib/libwebsockets.h
    @@ -166,7 +166,7 @@ struct sockaddr_in;
     #endif
    
     #ifdef LWS_USE_LIBEV
    -#include <ev.h>
    +#include <uv.h>
     #endif /* LWS_USE_LIBEV */
    
     #ifndef LWS_EXTERN
    @@ -1453,17 +1453,17 @@ LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
     lws_http_transaction_completed(struct lws *wsi);
    
     #ifdef LWS_USE_LIBEV
    -typedef void (lws_ev_signal_cb)(EV_P_ struct ev_signal *w, int revents);
    +typedef void (lws_ev_signal_cb)(uv_loop_t *l, uv_signal_t *w, int revents);
    
     LWS_VISIBLE LWS_EXTERN int
     lws_sigint_cfg(struct lws_context *context, int use_ev_sigint,
               lws_ev_signal_cb *cb);
    
     LWS_VISIBLE LWS_EXTERN int
    -lws_initloop(struct lws_context *context, struct ev_loop *loop);
    +lws_initloop(struct lws_context *context, uv_loop_t *loop);
    
     LWS_VISIBLE void
    -lws_sigint_cb(struct ev_loop *loop, struct ev_signal *watcher, int revents);
    +lws_sigint_cb(uv_loop_t *loop, uv_signal_t *watcher, int revents);
     #endif /* LWS_USE_LIBEV */
    
     LWS_VISIBLE LWS_EXTERN int
    diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h
    index 72f71b4..d20da12 100644
    --- a/lib/private-libwebsockets.h
    +++ b/lib/private-libwebsockets.h
    @@ -117,7 +117,7 @@
     #include <arpa/inet.h>
     #include <poll.h>
     #ifdef LWS_USE_LIBEV
    -#include <ev.h>
    +#include <uv.h>
     #endif /* LWS_USE_LIBEV */
     #include <sys/mman.h>
    
    @@ -439,12 +439,12 @@ struct lws;
    
     #ifdef LWS_USE_LIBEV
     struct lws_io_watcher {
    -   struct ev_io watcher;
    +    uv_poll_t watcher;
        struct lws_context* context;
     };
    
     struct lws_signal_watcher {
    -   struct ev_signal watcher;
    +    uv_signal_t watcher;
        struct lws_context* context;
     };
     #endif /* LWS_USE_LIBEV */
    @@ -560,7 +560,7 @@ struct lws_context {
        struct lws **lws_lookup;  /* fd to wsi */
     #endif
     #ifdef LWS_USE_LIBEV
    -   struct ev_loop* io_loop;
    +    uv_loop_t *io_loop;
        struct lws_io_watcher w_accept;
        struct lws_signal_watcher w_sigint;
        lws_ev_signal_cb* lws_ev_sigint_cb;
    
    opened by ghost 107
  • Socket adoption

    Socket adoption

    Hi.

    You remember when I talked about the need for load balancing in libwebsockets, and when you added the threading and built-in load balancer? This is nice and all, but I cannot really use it since our server already creates the threads and runs one context inside this already created thread(s), not the other way around.

    Also, when doing the wrapper I have gotten requests to support "connection hand-off" from Node.js's built-in HTTP support. They want to use the Node.js HTTP server up until the upgrade request comes and then swap to libwebsockets for WebSockets. I know how to get the file descriptor of the socket so it should be easy to add.

    So I'm thinking of a very basic support (to begin with) where you can bypass the listener and go straight to polling on a foreign file descriptor. This is one already implemented function in another WebSocket library (ws):

    server.handleUpgrade(request, socket, upgradeHead, callback)

    Handles a HTTP Upgrade request. request is an instance of http.ServerRequest, socket is an instance of net.Socket.
    
    When the Upgrade was successfully, the callback will be called with a ws.WebSocket object as parameter.
    

    So basically you get a fd and a upgrade header and from this you can create and "adopt" this foreign websocket. Thoughts? HTTPS to WSS is going to be a bigger problem though.

    Edit: (and regarding the load balancing - this is going to make it possible to have your own (external) load balancer, so it solves both problems in one. The load balancer can be done using regular Unix sockets and a listener and when a connection comes you get the fd and call this "handleUpgrade" function with the least loaded context)

    opened by ghost 83
  • max frame size / rx buffer send limitation

    max frame size / rx buffer send limitation

    why is libwebsocket_write limited by that, my previous build was not limited now i get ERROR writing, solved by increasing the max frame size / rx buffer to the size im trying to send.

    but this wont fix my problem because i have big variances in the sizes im sending.

    opened by gaby64 78
  • http problems across router

    http problems across router

    i just got a new router, previous problem of partial page load is still present

    websocket is working fine

    loading a 22414bytes page, the last 1kb is missing

    im hoping if this can be resolved i can resolve an issue im having with my own library and mangled data across the router. no problems directly connecting to the modem.

    opened by gaby64 66
  • .NET Client gets disconnected with 1002

    .NET Client gets disconnected with 1002

    Hello Team! You are doing a great work indeed! There is a small (I hope) problem here. It stands like this: There is a linux (ubuntu 18.04) web-socket server, based on minimal-ws-server-threads example If I connect to the ws server from Mozilla WebSocket addon it works no issues. But if my colleagues are trying to connect using .NET WebSocket Client submitting number of messages in a row (like 100 every 50ms) the client gets disconnected with 1002 WebSocket error I have verbosed the logging to maximum:

    int logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE
               | LLL_INFO    | LLL_PARSER                
                             | LLL_HEADER                
               | LLL_EXT | LLL_CLIENT                    
               | LLL_LATENCY                             
               | LLL_DEBUG                               
    ;
    

    Yet I do not observer any errors into the logs. What we did we have extended the buffer size for a protocol:

    #define LWS_PLUGIN_PROTOCOL_MINIMAL             \
       {                                            \
          "lws-minimal",                            \
          callback_minimal,                         \
          sizeof(struct per_session_data__minimal), \
          32768*1024,                               \
          0, NULL, 4096                             \
       }
    

    And it helped! It was purely experimental trick. But it hasn't resolved the prb completely. If the client starts sending messages with no delay the server gets disconnected after 15-20 messages.

    It all looks odd. I can provide logging, but they are huge and no errors into these, therefore it does not seem to be a worthy enterprise.

    Can you help with this?

    Thanks in advance George

    sample message snippet from Mozilla's addon:

    
    CLNT >> SRV: {"rqst":"auth","apikey":"key-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"}
    
    SRV >> CLNT: {"rqst":"auth","apikey":"key-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX","rspns":"ok"}
    
    CLNT >> SRV: {"cliOrderId":"WSTestNew84","price":"1","type":"lmt","tradingPairId":29,"amount":"1","side":"sell","rqst":"onew"}
    
    SRV >> CLNT: {"cliOrderId":"WSTestNew84","price":"1","type":"lmt","tradingPairId":29,"amount":"1","side":"sell","rqst":"onew","orderId":"[email protected]","ug":13,"action":1,"userId":51983,"rspns":"ok"}
    
    SRV >> CLNT: {"id":"[email protected]","userId":51983,"currencyId":1,"amount":"10000","lockedByOrder":"140","lockedByWithdrawal":"0","fee":"0","result":"1"}
    
    SRV >> CLNT: {"avgPrice":"0","cliOrderId":"WSTestNew84","execPrice":"1","initPrice":"1","message":"","oqty":"1","orderId":"[email protected]","qty":"1","side":"sell","stat":"accepted","tradingPairId":29,"trdId":"1552393109.603879.3.ug13","type":"lmt","ug":13,"userId":51983,"userIdMaker":0,"userIdTaker":0}
    
    
    
    
    opened by GeorgeShagov 65
  • lws_client_connect_via_info blocked

    lws_client_connect_via_info blocked

    On my test lws_client_connect_via_info take few secends to finish some time.

    Is there some call inside this function will block ( non asynchronous oprate) ?

    some time it take 137ms, some time 12048ms.

    This block my event loop, how to avoid this block ?

    opened by calvin2021y 62
  • lws_client_connect_via_info() trying to connect to IPv4 with AF_INET6! LWS 3.2.1

    lws_client_connect_via_info() trying to connect to IPv4 with AF_INET6! LWS 3.2.1

    Here's an strace, I bolded the important parts.

    rt_sigaction(SIGPIPE, {sa_handler=SIG_IGN, sa_mask=[RT_68 RT_70 RT_71 RT_73 RT_74 RT_75 RT_77 RT_79 RT_81 RT_83 RT_84 RT_86 RT_87 RT_88 RT_89 RT_90 RT_91 RT_93 RT_94 RT_95], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=NULL}, {sa_handler=SIG_IGN, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=NULL}, 16) = 0 prlimit64(0, RLIMIT_NOFILE, NULL, {rlim_cur=1024, rlim_max=4*1024}) = 0 open("/dev/urandom", O_RDONLY|O_LARGEFILE) = 4 fcntl64(4, F_SETFD, FD_CLOEXEC) = 0 pipe2([5, 6], O_NONBLOCK) = 0 getpid() = 1792 clock_gettime(CLOCK_BOOTTIME, {tv_sec=806, tv_nsec=921239425}) = 0 getpid() = 1792 getpid() = 1792 clock_gettime(CLOCK_BOOTTIME, {tv_sec=806, tv_nsec=930113942}) = 0 getpid() = 1792 getpid() = 1792 clock_gettime(CLOCK_BOOTTIME, {tv_sec=806, tv_nsec=934245716}) = 0 getpid() = 1792 getpid() = 1792 clock_gettime(CLOCK_BOOTTIME, {tv_sec=806, tv_nsec=937542694}) = 0 getpid() = 1792 getuid() = 0 geteuid() = 0 getgid() = 0 getegid() = 0 open("/etc/ssl/cert.pem", O_RDONLY|O_LARGEFILE) = 7 read(7, "-----BEGIN CERTIFICATE-----\nMIIH"..., 1024) = 1024 read(7, "xFwYIRKQ26ZIMApcQrAZQIDAQABo4ICy"..., 1024) = 1024 read(7, "gIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPN"..., 1024) = 1024 read(7, "AiIwDQYJKoZIhvcNAQEBBQADggIPADCC"..., 1024) = 1024 read(7, "8B1\nRXxlDPiyN8+sD8+Nb/kZ94/sHvJw"..., 1024) = 1024 read(7, "eQWN0YWxpcyBBdXRoZW50aWNhdGlvbiB"..., 1024) = 1024 read(7, "msGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4l"..., 1024) = 1024 read(7, "AGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYW"..., 1024) = 1024 read(7, "sxOBi0cQ+azcgOno4uG+GMmIPLHzHxRE"..., 1024) = 1024 read(7, "d6M06uJFdhrJNTxFq7YpFzUf1GO7RgBs"..., 1024) = 1024 read(7, "HQ4EFgQUBx/S55zawm6i\nQLSwelAQUHT"..., 1024) = 1024 read(7, "8rNrS\ns8PhaJyJ+HoAVt70VZVs+7pk3W"..., 1024) = 1024 read(7, "k4gmVBtWVyuEklut89pMF\nu+1z6S3RdT"..., 1024) = 1024 read(7, "W+uZPpY5Yse42O+tYHNbwKMeQ==\n----"..., 1024) = 1024 read(7, "E6V/Uq2V8viTO96LXFvKWlJbYK8U90vv"..., 1024) = 1024 read(7, "j\nmUyl+17vIWR6IF9sZIUVyzfpYgwLKh"..., 1024) = 1024 read(7, "H+fO6AgonB8Xx1sfT\n4PsJYGw=\n-----"..., 1024) = 1024 read(7, "BBAAiA2IABNKrijdPo1MN/sGKe0uoe0Z"..., 1024) = 1024 read(7, "nezG8HDt0L\ncp2AMBYHlT8oDv3FdU9T1"..., 1024) = 1024 read(7, "DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO"..., 1024) = 1024 read(7, "wBl\nAGwAbwBuAGEAIAAwADgAMAAxADcw"..., 1024) = 1024 read(7, "LMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJ"..., 1024) = 1024 read(7, "N CERTIFICATE-----\nMIIFWTCCA0GgA"..., 1024) = 1024 read(7, "71bbRuMGjeyNYmsHVee7QHIJihdjK4TW"..., 1024) = 1024 read(7, "AMMF0J1eXBhc3Mg\nQ2xhc3MgMyBSb290"..., 1024) = 1024 read(7, "jANBgkqhkiG9w0BAQsFAAOCAgEAACAj\n"..., 1024) = 1024 read(7, "YXRpc2xhdmEx\nEzARBgNVBAoTCkRpc2l"..., 1024) = 1024 read(7, "bYVybqjGom32+nNjf7xueQgcnYqf\nGop"..., 1024) = 1024 read(7, "wggIKAoICAQDXXWvNED8fBVnVBU03\nsQ"..., 1024) = 1024 read(7, "96/Ua4CUqmtzHQTb3yHQFhDmVOdYLO6Q"..., 1024) = 1024 read(7, "9NT0RPIENlcnRpZmljYXRpb24gQXV0\na"..., 1024) = 1024 read(7, "IFICATE-----\n-----BEGIN CERTIFIC"..., 1024) = 1024 read(7, "NBgkqhkiG9w0BAQwFADCB\nhTELMAkGA1"..., 1024) = 1024 read(7, "qR84onAZFdr+CGCe01a60y1Dma/RMhnE"..., 1024) = 1024 read(7, "DCCApCgAwIBAgIJAP7c4wEPyUj/MA0GC"..., 1024) = 1024 read(7, "zRgzB7mFnc\nfca5DClMoTOi62c6ZYTTl"..., 1024) = 1024 read(7, "+PhmiM1b8XcF4LVzbsF9Ri6OSyemzTUK"..., 1024) = 1024 read(7, "0AMRgwj\nY/M50n92Uaf0yKHxDHYiI0ZS"..., 1024) = 1024 read(7, "\nQgEBBAQDAgEGMDcGA1UdHwQwMC4wLKA"..., 1024) = 1024 madvise(0x84b000, 520192, MADV_DONTNEED) = 0 read(7, "ptJ11/91sts1rH\nUV+rpDKmYYe2bg+G0"..., 1024) = 1024 read(7, "EF1dGhvcml0eTEkMCIG\nA1UEAxMbQ2Vy"..., 1024) = 1024 read(7, "53/twIDAQABo0IwQDAPBgNVHRMBAf8EB"..., 1024) = 1024 read(7, "pcm1hLmNvbS9hZGRyZXNzKTESMBAGA1U"..., 1024) = 1024 read(7, "\nWk0ZN5K3xMGtr/R5JJqyAQuxr1yW84A"..., 1024) = 1024 read(7, "MjNbMMeJL0eYD6MD\nxvbxrN8y8NmBGuS"..., 1024) = 1024 read(7, "WCwEiwqJH5YZ92IFCokcdmtet4\nYgNW8"..., 1024) = 1024 read(7, "bCBSb290MB4XDTA2MTIxNTA4MDAwMFoX"..., 1024) = 1024 read(7, "B+TX3EJIrduPuoc\nA06dGiBh+4E37F78"..., 1024) = 1024 read(7, "0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCU"..., 1024) = 1024 read(7, "COvXwEz75ivJn9gpfSegpn\nljgJ9hBOl"..., 1024) = 1024 read(7, "a1CInXCGNjOCd1HjPqbqjdn5lPdE2BiY"..., 1024) = 1024 read(7, "cz8faXbauX+5v3gTt23ADq1cEmv8uXr\n"..., 1024) = 1024 read(7, "TNXeWHmb0moc\nQqvF1afPaA+W5OFhmHZ"..., 1024) = 1024 read(7, "UAA4IBDwAwggEKAoIBAQCtDhXO5EOAXL"..., 1024) = 1024 read(7, "zEVMBMGA1UEChMMRGlnaUNlcnQgSW5jM"..., 1024) = 1024 read(7, "5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7"..., 1024) = 1024 read(7, "----BEGIN CERTIFICATE-----\nMIIDr"..., 1024) = 1024 read(7, "TnmCmrEbXjcKChzUyImZOMkXDiqw8cvp"..., 1024) = 1024 read(7, "XOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ\n"..., 1024) = 1024 read(7, "LfyHS8L6+c/MzXRq8NOrexpu80JX28Mz"..., 1024) = 1024 read(7, "nHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnr"..., 1024) = 1024 read(7, "EwJV\nUzEVMBMGA1UEChMMRGlnaUNlcnQ"..., 1024) = 1024 read(7, "mbnJeFwMDF/k5hQpVgs2\nSV1EY+CtnJY"..., 1024) = 1024 read(7, "0OFoXDTIz\nMDMwMzEyMDk0OFowgbIxCz"..., 1024) = 1024 read(7, "DVR0OBBYEFC7j27JJ0JxUeVz6\nJyr+zE"..., 1024) = 1024 read(7, "EgZGUgQ2Vy\ndGlmaWNhY2lvIChOSUYgU"..., 1024) = 1024 read(7, "IimAy4E5S2S+zw0JDnJwIDAQAB\no4HjM"..., 1024) = 1024 read(7, "DEy\nMTcyMzU5NTlaMHUxCzAJBgNVBAYT"..., 1024) = 1024 read(7, "Ddr5rMzcijJs1eg9gIW\niAYLtqZLICjU"..., 1024) = 1024 read(7, "PKQP5L6RQstRIzgUyVYr9smRMDuSYB3X"..., 1024) = 1024 read(7, "RydXN0LCBJbmMuMTkw\nNwYDVQQLEzB3d"..., 1024) = 1024 read(7, "ua2J7p8eRDjeIRRDq/r72DQnNSi6q7py"..., 1024) = 1024 read(7, "KlH\nBz7MIKNCMEAwDgYDVR0PAQH/BAQD"..., 1024) = 1024 read(7, "s1/T\nRU4cctZOMvJyig/3gxnQaoCAAEU"..., 1024) = 1024 read(7, "A1MTMxNVoXDTQwMTIzMTE1NTk1OVowYj"..., 1024) = 1024 read(7, "CAQDRSVfg\np8xoWLoBDysZzY2wYUWsEe"..., 1024) = 1024 read(7, "ENBMIIBIjANBgkqhkiG9w0BAQEFAAOCA"..., 1024) = 1024 read(7, "EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg"..., 1024) = 1024 read(7, "8Fj\nUjPtp8nSOQJw+uCxQmYpqptR7TBU"..., 1024) = 1024 read(7, "gpxgceeHHNgIwOlavmnRs9vuD4DPTCF+"..., 1024) = 1024 read(7, "F/BqxqjsHQ9gUdfeZC\nhuOl1UcCAwEAA"..., 1024) = 1024 read(7, "N+yFFXoZCPzVx5zw8qkuEKmS5j1YPakW"..., 1024) = 1024 read(7, "Pnbiucon8l+f725ZDQbYKxek0nxru18U"..., 1024) = 1024 read(7, "\nse4YuU6W3Nx2/zu+z18DwPw76L5GG//"..., 1024) = 1024 read(7, "8RW04eWe3fiPpm8m\n1wk8OhwRDqZsN/e"..., 1024) = 1024 read(7, "IN CERTIFICATE-----\nMIICHjCCAaSg"..., 1024) = 1024 read(7, "xMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRk"..., 1024) = 1024 read(7, "----BEGIN CERTIFICATE-----\nMIIDu"..., 1024) = 1024 read(7, "EbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0"..., 1024) = 1024 read(7, "RPvm2L7DWzgVGkWqQPabumDk3F2xmmFg"..., 1024) = 1024 read(7, "E3nOUTvOniX9PeGMIyBJQbUJmL025eSh"..., 1024) = 1024 read(7, "qW/hpvvf\ncDDpw+5CRu3CkwWJ+n1jez/"..., 1024) = 1024 read(7, "BDaGFtYmVyc2lnbiBSb290IC0gMjAwOD"..., 1024) = 1024 read(7, "VzcykxEjAQBgNVBAUTCUE4Mjc0MzI4Nz"..., 1024) = 1024 read(7, "IIEADCCAuigAwIBAgIBADANBgkqhkiG9"..., 1024) = 1024 read(7, "ZIhvcNAQEFBQAD\nggEBADJL87LKPpH8E"..., 1024) = 1024 read(7, "dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZ"..., 1024) = 1024 read(7, "v\nb3RDQSAyMDE1MB4XDTE1MDcwNzEwMz"..., 1024) = 1024 read(7, "Dk1MloXDTMxMTIwMTEzNDk1MlowgZUxC"..., 1024) = 1024 read(7, "ZJwzNzvoc7\ndIsXRSZMFpGD/md9zU1jZ"..., 1024) = 1024 read(7, "5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDP"..., 1024) = 1024 read(7, "DlZdwJVqwjbDG2jJ9SrcR5q+ss7FJej6"..., 1024) = 1024 read(7, "VHRMBAf8ECDAGAQH/AgED\nMA4GA1UdDw"..., 1024) = 1024 read(7, "IB0ttov0DiNewNwIRt18jA8+o+u3dpjq"..., 1024) = 1024 read(7, "JUagEiuTDkHzsxHpFKVK7q4+63SM1N95"..., 1024) = 1024 read(7, "dBeo0XKIanoBScy0RnnGF7HamB4HWfp1"..., 1024) = 1024 read(7, "Xjtw+hG\n4iZZRHUe2XWJUc0QhJ1hYMtd"..., 1024) = 1024 read(7, "xkA2T26pEUWbMfXYD62qoKjgZl3YNa4p"..., 1024) = 1024 read(7, "q4/i6jC8UDfv\n8Ue1fXwsBOxonbRJRBD"..., 1024) = 1024 read(7, "UD8r6ddIB\nQFqNeb+Lz0vPqhbBleStTI"..., 1024) = 1024 read(7, "TrdZoQ0iy2+tzJOeRf1SktoA+\nnaM8TH"..., 1024) = 1024 read(7, "AiS8sIm7vI+AIpHb4g\nDEa/a4ebsypmQ"..., 1024) = 1024 read(7, "Qc7kGUnF4ZLvhFSZl0kbAEb+MEWrGrKq"..., 1024) = 1024 read(7, "qH5GoP7ghu5sJf0dgYzQ0mg/wu1\n+rUC"..., 1024) = 1024 read(7, "DAxOZXRM\nb2NrIEtmdC4xNzA1BgNVBAs"..., 1024) = 1024 read(7, "8ZvYzsRjdT9ZR7E=\n-----END CERTIF"..., 1024) = 1024 read(7, "ydGlmaWNhdGVBdXRob3Jp\ndHkuY3JsMA"..., 1024) = 1024 read(7, "OVTJoZIyEVRd7jyBxR\nVVuuk+g3/ytr6"..., 1024) = 1024 read(7, "A1UEAxMfT0lTVEUgV0lTZUtleSBHbG9i"..., 1024) = 1024 read(7, "8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU"..., 1024) = 1024 read(7, "--\n-----BEGIN CERTIFICATE-----\nM"..., 1024) = 1024 read(7, "G+WAABMIH7MIHUBggrBgEFBQcCAjCBxx"..., 1024) = 1024 read(7, "Q2+Q==\n-----END CERTIFICATE-----"..., 1024) = 1024 read(7, "y7IlXnLc6KO\nTk0k+17kBL5yG6YnLUla"..., 1024) = 1024 read(7, "\nGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl"..., 1024) = 1024 read(7, "hGK8SEwzJQTU7tD2\nA8QZRtGUazBuBgN"..., 1024) = 1024 read(7, "ELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEF"..., 1024) = 1024 read(7, "B/wQEAwIB\nBjAdBgNVHQ4EFgQU7edvdl"..., 1024) = 1024 read(7, "AYTAkJNMRkwFwYDVQQKExBRdW9WYWRpc"..., 1024) = 1024 read(7, "QgQ0EgMyBDZXJ0\naWZpY2F0ZSBQb2xpY"..., 1024) = 1024 read(7, "8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK\n4"..., 1024) = 1024 read(7, "AVuNVejH38DMdyM0SXV89pgR6y3e7UEu"..., 1024) = 1024 read(7, "BAgIILCmcWxbtBZUwCgYIKoZIzj0EAwI"..., 1024) = 1024 read(7, "QIDAVUZXhhczEQMA4GA1UEBwwHSG91c3"..., 1024) = 1024 read(7, "kiFCbLsjtzdFVHB3mBOagwE0TlBIqulh"..., 1024) = 1024 read(7, "gIIdebfy8FoW6gwCgYIKoZIzj0EAwIwf"..., 1024) = 1024 read(7, "DgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQK"..., 1024) = 1024 read(7, "6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRW"..., 1024) = 1024 read(7, "JKoZIhvcNAQEL\nBQAwUTELMAkGA1UEBh"..., 1024) = 1024 read(7, "RVOul4+vJhaAlIDf7js4MNIThPIGy\nd0"..., 1024) = 1024 read(7, "EB\nAKChOBZmLqdWHyGcBvod7bkixTgm2"..., 1024) = 1024 read(7, "01k/unK8RCSc43Oz969XL0Imnal0ugBS"..., 1024) = 1024 read(7, "lY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSq"..., 1024) = 1024 read(7, "ICATE-----\n-----BEGIN CERTIFICAT"..., 1024) = 1024 read(7, "vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7"..., 1024) = 1024 read(7, "7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T\n"..., 1024) = 1024 read(7, "P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jD"..., 1024) = 1024 read(7, "uU6TJJB79VWZxXSzFYGgEt9nC\nUiY4iK"..., 1024) = 1024 read(7, "HowNDXLldRqANb/9Zjr7dn3LDWyvfjFv"..., 1024) = 1024 read(7, "gpT0GtJlvOjCwV3SPcl5XCsMBQgJeN/d"..., 1024) = 1024 read(7, "wWVxJK\ngnjIFNkXgiYtXSAfea7+1HAWF"..., 1024) = 1024 read(7, "KL+tjzk7FqX\nxz8ecAgwoNzFs21v0IJy"..., 1024) = 1024 read(7, "Yox+wrZ13+b8KKaa8MFSu1BYBQw\n0aoR"..., 1024) = 1024 read(7, "cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj1"..., 1024) = 1024 read(7, "MsIEluYy4xMjAwBgNVBAMTKVN0YXJmaW"..., 1024) = 1024 read(7, "TlZFkSIHc40zI+OIF1lnP6aI+xy84fxe"..., 1024) = 1024 read(7, "7FrjSXZm86B0UVGMpZwh94CDklDhbZsc"..., 1024) = 1024 read(7, "oWACjR8cGp4QjK7u9lit/VcyLwVcfDmJ"..., 1024) = 1024 read(7, "/wySTVltpkuzFwbs4AOPsF6m43Md8AYO"..., 1024) = 1024 read(7, "mD9ui5aLlV8gREpzn5/ASLHvGiTSf5YX"..., 1024) = 1024 read(7, "9y7v5RoSJBsXECYxqCsGKrXlcSH9/L3X"..., 1024) = 1024 read(7, "GVsZVNlYyBHbG9iYWxSb290IENsYXNzI"..., 1024) = 1024 read(7, "pBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnB"..., 1024) = 1024 read(7, "uUg/vBa3wW30\n6gmv7PO15wWeph6KU1H"..., 1024) = 1024 read(7, "l8JoSNkvoBHToP4mQ4t4y86Ij5iySr\nL"..., 1024) = 1024 read(7, "TU5\nNTlaMFExCzAJBgNVBAYTAlRXMRIw"..., 1024) = 1024 read(7, "bDorMjupWkEmQqSpqsn\nLhpNgb+E1HAe"..., 1024) = 1024 read(7, "GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoI"..., 1024) = 1024 read(7, "BSb290IENlcnRpZmlj\nYXRpb24gQXV0a"..., 1024) = 1024 read(7, "VnKgMAAAQUA5vwIhP/lSg209yewDL7MT"..., 1024) = 1024 read(7, "bmVyYTEfMB0GA1UEAwwWVGVsaWFTb25l"..., 1024) = 1024 read(7, "0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q"..., 1024) = 1024 read(7, "\nIgYDVQQKDBtUcnVzdENvciBTeXN0ZW1"..., 1024) = 1024 read(7, "JcLmA4GLEFPjx1Wi\ntJ/X5g==\n-----E"..., 1024) = 1024 read(7, "ABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/\nD"..., 1024) = 1024 read(7, "VQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0"..., 1024) = 1024 read(7, "rWyOrsGS2h60COX\ndKcs8AjYeVrXWoSK"..., 1024) = 1024 read(7, "CASIwDQYJKoZIhvcNAQEBBQAD\nggEPAD"..., 1024) = 1024 read(7, "zARBgNVBAgTCk5ldyBKZXJzZXkxFDASB"..., 1024) = 1024 read(7, "aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAs"..., 1024) = 1024 read(7, "VS7qXMYoCAQlObgOK6nyTJccBz8NUvXt"..., 1024) = 1024 read(7, "uMR8wHQYDVQQLExZW\nZXJpU2lnbiBUcn"..., 1024) = 1024 read(7, "OzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVg"..., 1024) = 1024 read(7, "tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG\nB"..., 1024) = 1024 read(7, "QQLEzEoYykgMjAwOCBWZXJp\nU2lnbiwg"..., 1024) = 1024 read(7, "nZlcmlzaWduLmNvbS92c2xvZ28uZ2lmM"..., 1024) = 1024 read(7, "\nbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXN"..., 1024) = 1024 read(7, "FADCB\ngjELMAkGA1UEBhMCVVMxHjAcBg"..., 1024) = 1024 read(7, "wDQYJKoZIhvcNAQEFBQAD\nggEBAJEVOQ"..., 1024) = 1024 read(7, "AoEwF73XVv4EOLQunpL+943AAAaWyjj0"..., 1024) = 1024 read(7, "ywEhajfqhFAH\nSyZbCUNsIZ5qyNUD9WB"..., 1024) = 1024 read(7, "xrsStZf0X4OFunHB2WyBEXYKCrC/\ngpf"..., 1024) = 1024 read(7, "UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbm"..., 1024) = 1024 read(7, "FICATE-----\nMIICiDCCAg2gAwIBAgIQ"..., 1024) = 1024 read(7, "GA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd"..., 1024) = 1024 read(7, "ggEBABpA\n2JVlrAmSicY59BDlqQ5mU11"..., 1024) = 381 read(7, "", 1024) = 0 close(7) = 0 getuid() = 0 geteuid() = 0 getgid() = 0 getegid() = 0 uname({sysname="Linux", nodename="OpenWrt", ...}) = 0 write(6, "\0", 1) = 1 open("/etc/hosts", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 7 fcntl64(7, F_SETFD, FD_CLOEXEC) = 0 read(7, "127.0.0.1 localhost\n\n::1 loc"..., 1024) = 110 read(7, "", 1024) = 0 close(7) = 0 open("/etc/resolv.conf", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 7 fcntl64(7, F_SETFD, FD_CLOEXEC) = 0 read(7, "search lan\nnameserver 127.0.0.1\n", 248) = 32 read(7, "", 248) = 0 close(7) = 0 socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 7 bind(7, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("0.0.0.0")}, 16) = 0 sendto(7, "\305\247\1\0\0\1\0\0\0\0\0\0\3dev\25sundialcommunic"..., 47, MSG_NOSIGNAL, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.1")}, 16) = 47 sendto(7, "\333D\1\0\0\1\0\0\0\0\0\0\3dev\25sundialcommunic"..., 47, MSG_NOSIGNAL, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.1")}, 16) = 47 poll([{fd=7, events=POLLIN}], 1, 2500) = 1 ([{fd=7, revents=POLLIN}]) recvfrom(7, "\305\247\201\200\0\1\0\1\0\0\0\0\3dev\25sundialcommunic"..., 512, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.1")}, [16]) = 63 recvfrom(7, "\333D\201\200\0\1\0\0\0\0\0\0\3dev\25sundialcommunic"..., 512, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.1")}, [16]) = 47 close(7) = 0 socket(AF_INET6, SOCK_STREAM, IPPROTO_IP) = 7 fcntl64(7, F_SETFD, FD_CLOEXEC) = 0 setsockopt(7, SOL_TCP, TCP_NODELAY, [1], 4) = 0 fcntl64(7, F_SETFL, O_RDONLY|O_NONBLOCK|O_LARGEFILE) = 0 connect(7, {sa_family=AF_INET6, sin6_port=htons(8550), sin6_flowinfo=htonl(0), inet_pton(AF_INET6, "::ffff:18.237.74.173", &sin6_addr), sin6_scope_id=0}, 28) = -1 EINPROGRESS (Operation in progress) mmap2(NULL, 143360, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x77b83000 mprotect(0x77b85000, 135168, PROT_READ|PROT_WRITE) = 0 rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1 RT_2], [], 16) = 0 clone(child_stack=0x77ba5d48, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID|0x400000, parent_tid=[1799], tls=0x77bacdec, child_tidptr=0x77f6fff8) = 1799 rt_sigprocmask(SIG_SETMASK, [], NULL, 16) = 0 nanosleep({tv_sec=20, tv_nsec=0}, 0x7fb99c20) = 0 munmap(0x77f6c000, 4) = 0 open("/etc/TZ", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_CLOEXEC) = 8 fstat64(8, {st_mode=S_IFREG|0644, st_size=4, ...}) = 0 mmap2(NULL, 4, PROT_READ, MAP_SHARED, 8, 0) = 0x77f6c000 close(8) = 0 writev(2, [{iov_base="[2020/01/01 20:35:16:7749] E: ", iov_len=30}, {iov_base="CLIENT_CONNECTION_ERROR: closed "..., iov_len=51}], 2) = 81 writev(2, [{iov_base="", iov_len=0}, {iov_base=NULL, iov_len=0}], 2) = 0 close(7) = 0 poll([{fd=5, events=POLLIN}], 1, 1004) = 1 ([{fd=5, revents=POLLIN}]) read(5, "\0", 100) = 1 tkill(1799, SIGRT_1) = 0 futex(0x77ba5dd8, FUTEX_WAKE_PRIVATE, 1) = 1 close(5) = 0 close(6) = 0 close(4)

    As you can see, LWS initializes fine and reads all of the ssl certs as it should but when it comes to connecting it is trying to use ::ffff:18.237.74.173 as AF_INET6 and the domain name it's resolving does not even have an IPv6 aaaa record.

    I realize I can look up the address with gethostbyname or gethostbyname2 for AF_INET or AF_INET6 only but I was hoping that the lws implementation would properly resolve the name to a working address in a class that exists on this host.

    Here's the initialization code I am using:

        struct lws_context_creation_info info;
        struct lws_client_connect_info i;
        struct lws_context *context;
        int             n = 0,
    	logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE
    	/*
    	 * for LLL_ verbosity above NOTICE to be built into lws, lws must
    	 * have been configured with -DCMAKE_BUILD_TYPE=DEBUG instead of
    	 * =RELEASE 
    	 */
    	/*
    	 * | LLL_INFO 
    	 *//*
    	 * | LLL_PARSER 
    	 *//*
    	 * | LLL_HEADER 
    	 */
    	/*
    	 * | LLL_EXT 
    	 *//*
    	 * | LLL_CLIENT 
    	 *//*
    	 * | LLL_LATENCY 
    	 */
    	/*
    	 * | LLL_DEBUG 
    	 */ ;
    
        lws_set_log_level(logs, NULL);
    
        memset(&info, 0, sizeof info);	/* otherwise uninitialized garbage 
    					 */
        info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
        info.port = CONTEXT_PORT_NO_LISTEN;	/* we do not run any server */
        info.protocols = protocols;
    
        /*
         * since we know this lws context is only ever going to be used with
         * one client wsis / fds / sockets at a time, let lws know it doesn't
         * have to use the default allocations for fd tables up to ulimit -n.
         * It will just allocate for 1 internal and 1 (+ 1 http2 nwsi) that we
         * will use.
         */
        info.fd_limit_per_thread = 1 + 1 + 1;
    
        context = lws_create_context(&info);
        if (!context) {
    	printf("lws init failed\n");
    	lwsl_err("lws init failed\n");
    	return;
        }
    
        memset(&i, 0, sizeof i);	/* otherwise uninitialized garbage */
        i.context = context;
        i.port = root_port;
        i.address = root_address;
        i.path = "/ws";
        i.host = i.address;
        i.origin = i.address;
        i.ssl_connection = LCCSCF_USE_SSL;
        i.protocol = protocols[0].name;
        i.pwsi = &client_wsi;
        // i.alpn = "h2"; // set to support ALPN and http/2
    
        lws_client_connect_via_info(&i);
    
        // wait for everything to initialize
        sleep(20);
    
        while (n >= 0 && client_wsi)
    	n = lws_service(context, 0);
    
        // destroy the lws context
        lws_context_destroy(context);
    

    LWS is version 3.2.1 Distribution is Openwrt Trunk (latest as of today)

    Here is some more system information.

    [email protected]:~# dmesg|grep SoC
    [    0.000000] SoC: Atheros AR9330 rev 1
    [email protected]:~# cat /proc/cpuinfo 
    system type		: Atheros AR9330 rev 1
    machine			: Ubiquiti AirGateway
    processor		: 0
    cpu model		: MIPS 24Kc V7.4
    BogoMIPS		: 258.04
    wait instruction	: yes
    microsecond timers	: yes
    tlb_entries		: 16
    extra interrupt vector	: yes
    hardware watchpoint	: yes, count: 4, address/irw mask: [0x0ffc, 0x0ffc, 0x0ffb, 0x0ffb]
    isa			: mips1 mips2 mips32r1 mips32r2
    ASEs implemented	: mips16
    Options implemented	: tlb 4kex 4k_cache prefetch mcheck ejtag llsc dc_aliases perf_cntr_intr_bit nan_legacy nan_2008 perf
    shadow register sets	: 1
    kscratch registers	: 0
    package			: 0
    core			: 0
    VCED exceptions		: not available
    VCEI exceptions		: not available
    
    opened by andrewhodel 61
  • Libwebsockets 4.1.6 without libevent and external loop

    Libwebsockets 4.1.6 without libevent and external loop

    Is there any option to integrate the libwebsocket with an external loop (i am using uloop) without depending of libevent?

    I can´t use for example eventfd_write function of libwebsockets.

    opened by fusionJose 59
  • tls: error:00000001:lib(0):func(0):reason(1)

    tls: error:00000001:lib(0):func(0):reason(1)

    Hello libwebsockets Team!

    During connection to ws-api.kucoin.com I'm receiveing this erro

    tls: error:00000001:lib(0):func(0):reason(1)

    Error comes from lws_service(struct lws_context *context, int timeout_ms) lib\core-net\service.c

    Code was tested on Win and Unix environments and on both same error was accured image image

    Think about some lws_client_connect_ssl_connection_flags aditional option setup but have no idea which one can be added to next set LCCSCF_USE_SSL | LCCSCF_ALLOW_SELFSIGNED | LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK which was already tested

    Will be apprecated for some steps to fix it.

    opened by ylozitski 55
  • Crashes during Codenomicon testing

    Crashes during Codenomicon testing

    This may not be the most useful bug report at the moment, but I'll try getting other information that might be useful here. When running the Codenomicon test suite against our product, we've noticed a couple of crashes in libwebsocket.

    I've tried debugging this, but haven't made much progress. There might be multiple crashes here.

    • Original backtrace I was working with was (this was using libwebsockets 1.5): #0 0x00007fb6fd8e45c9 in raise () from /lib64/libc.so.6 #1 0x00007fb6fd8e5cd8 in abort () from /lib64/libc.so.6 #2 0x00007fb6fd924db7 in __libc_message () from /lib64/libc.so.6 #3 0x00007fb6fd92c19d in _int_free () from /lib64/libc.so.6 #4 0x0000000000cda733 in _realloc () #5 0x0000000000cd8da2 in lws_free_header_table () #6 0x0000000000cdf4d4 in lws_handshake_server () #7 0x0000000000ce11ac in libwebsocket_read () #8 0x0000000000cdf7b3 in lws_server_socket_service () #9 0x0000000000cd7996 in libwebsocket_service_fd () #10 0x0000000000cde530 in lws_plat_service () #11 0x0000000000c76a39 in websocket_server_thread (context=) at [path]/websocket_server.cpp:429 #12 0x00007fb6fdc77df3 in start_thread () from /lib64/libpthread.so.0 #13 0x00007fb6fd9a51ad in clone () from /lib64/libc.so.6
    • I upgraded to libwebsockets 1.6 and tried the tests again, and it crashed with (when running in gdb): #0 0x0000000001035687 in lws_parse () #1 0x000000000103b43a in lws_handshake_server () #2 0x000000000103d255 in lws_read () #3 0x000000000103bc53 in lws_server_socket_service () #4 0x0000000001033d06 in lws_service_fd () #5 0x000000000103a778 in lws_plat_service () #6 0x0000000000fe19f9 in websocket_server_thread (context=[optimised out]) at [path]/websocket_server.cpp:427 #7 0x00007ffff61b5e9a in start_thread (arg=0x7fffa5d90700) at pthread_create.c:308 #8 0x00007ffff5ee338d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #9 0x0000000000000000 in ?? ()
    • I tried running in valgrind, and it crashed with: ==7726== Invalid write of size 1 ==7726== at 0x1036279: lws_rx_sm (in [application]) ==7726== by 0x103BF3F: lws_interpret_incoming_packet (in [application]) ==7726== by 0x103D397: lws_read (in [application]) ==7726== by 0x1033DDA: lws_service_fd (in [application]) ==7726== by 0x103A777: lws_plat_service (in [application]) ==7726== by 0xFE19F8: websocket_server_thread(void_) (websocket_server.cpp:427) ==7726== by 0x6848E99: start_thread (pthread_create.c:308) ==7726== by 0x6B5138C: clone (clone.S:112) ==7726== Address 0x41633dd0 is not stack'd, malloc'd or (recently) free'd ==7726== ==7726== ==7726== Process terminating with default action of signal 11 (SIGSEGV) ==7726== Access not within mapped region at address 0x41633DD0 ==7726== at 0x1036279: lws_rx_sm (in [application]) ==7726== by 0x103BF3F: lws_interpret_incoming_packet (in [application]) ==7726== by 0x103D397: lws_read (in [application]) ==7726== by 0x1033DDA: lws_service_fd (in [application]) ==7726== by 0x103A777: lws_plat_service (in [application]) ==7726== by 0xFE19F8: websocket_server_thread(void_) (websocket_server.cpp:427) ==7726== by 0x6848E99: start_thread (pthread_create.c:308) ==7726== by 0x6B5138C: clone (clone.S:112) ==7726== If you believe this happened as a result of a stack ==7726== overflow in your program's main thread (unlikely but ==7726== possible), you can try to increase the size of the ==7726== main thread stack using the --main-stacksize= flag. ==7726== The main thread stack size used in this run was 8388608.

    I think this last crash is due to out-of-bounds array access at parsers.c:860

        if (wsi->u.ws.all_zero_nonce)
            wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
                   (wsi->u.ws.rx_user_buffer_head++)] = c;
    

    but I couldn't work out where 'rx_user_buffer_head' was getting corrupted.

    What other information would be useful here? I can try and get a packet capture of the traffic around the time of the crash (but we currently use secure websockets, so I'll probably have to change that first).

    opened by aatukora 51
  • Add example for auth digest processing with user callback

    Add example for auth digest processing with user callback

    Hi, As i propose in issue, here is a simple example on how to process the Auth Digest authentification with user callback. Waiting for your comment BR Simon

    opened by simon0356 1
  • workflows: add cifuzz action

    workflows: add cifuzz action

    Add CIFuzz workflow action to have fuzzers build and run on each PR. This is a service offered by OSS-Fuzz, on which libwebsockets was recently integrated into. CIFuzz can help detect catch regressions and fuzzing build issues early, and has a variety of features (see the URL above). In the current PR the fuzzer is built on a pull request and will run for 300 seconds.

    Signed-off-by: David Korczynski [email protected]

    opened by DavidKorczynski 0
  • Add CodeQL workflow for GitHub code scanning

    Add CodeQL workflow for GitHub code scanning

    Hi warmcat/libwebsockets!

    This is a one-off automatically generated pull request from LGTM.com :robot:. You might have heard that we’ve integrated LGTM’s underlying CodeQL analysis engine natively into GitHub. The result is GitHub code scanning!

    With LGTM fully integrated into code scanning, we are focused on improving CodeQL within the native GitHub code scanning experience. In order to take advantage of current and future improvements to our analysis capabilities, we suggest you enable code scanning on your repository. Please take a look at our blog post for more information.

    This pull request enables code scanning by adding an auto-generated codeql.yml workflow file for GitHub Actions to your repository — take a look! We tested it before opening this pull request, so all should be working :heavy_check_mark:. In fact, you might already have seen some alerts appear on this pull request!

    Where needed and if possible, we’ve adjusted the configuration to the needs of your particular repository. But of course, you should feel free to tweak it further! Check this page for detailed documentation.

    Questions? Check out the FAQ below!

    FAQ

    Click here to expand the FAQ section

    How often will the code scanning analysis run?

    By default, code scanning will trigger a scan with the CodeQL engine on the following events:

    • On every pull request — to flag up potential security problems for you to investigate before merging a PR.
    • On every push to your default branch and other protected branches — this keeps the analysis results on your repository’s Security tab up to date.
    • Once a week at a fixed time — to make sure you benefit from the latest updated security analysis even when no code was committed or PRs were opened.

    What will this cost?

    Nothing! The CodeQL engine will run inside GitHub Actions, making use of your unlimited free compute minutes for public repositories.

    What types of problems does CodeQL find?

    The CodeQL engine that powers GitHub code scanning is the exact same engine that powers LGTM.com. The exact set of rules has been tweaked slightly, but you should see almost exactly the same types of alerts as you were used to on LGTM.com: we’ve enabled the security-and-quality query suite for you.

    How do I upgrade my CodeQL engine?

    No need! New versions of the CodeQL analysis are constantly deployed on GitHub.com; your repository will automatically benefit from the most recently released version.

    The analysis doesn’t seem to be working

    If you get an error in GitHub Actions that indicates that CodeQL wasn’t able to analyze your code, please follow the instructions here to debug the analysis.

    How do I disable LGTM.com?

    If you have LGTM’s automatic pull request analysis enabled, then you can follow these steps to disable the LGTM pull request analysis. You don’t actually need to remove your repository from LGTM.com; it will automatically be removed in the next few months as part of the deprecation of LGTM.com (more info here).

    Which source code hosting platforms does code scanning support?

    GitHub code scanning is deeply integrated within GitHub itself. If you’d like to scan source code that is hosted elsewhere, we suggest that you create a mirror of that code on GitHub.

    How do I know this PR is legitimate?

    This PR is filed by the official LGTM.com GitHub App, in line with the deprecation timeline that was announced on the official GitHub Blog. The proposed GitHub Action workflow uses the official open source GitHub CodeQL Action. If you have any other questions or concerns, please join the discussion here in the official GitHub community!

    I have another question / how do I get in touch?

    Please join the discussion here to ask further questions and send us suggestions!

    opened by lgtm-com[bot] 0
  • unordered continuation error at client-parser-ws.c#84 is only an info message

    unordered continuation error at client-parser-ws.c#84 is only an info message

    Accidentally sending \r\n\r\n\0 instead of just \r\n\r\n at the end of a handshake will have LWS correctly treat the \0 as separate packet. That packet then is interpreted to have fin=0 and opcode=0 without having received a first fragment prior.

    Would it be appropriate to upgrade the info to an error message (since it does destroy the connection) ?

    opened by Ninetalesgh 1
  • _lws_b64_decode_string is broken with lws-minimal-http-server-basicauth

    _lws_b64_decode_string is broken with lws-minimal-http-server-basicauth

    I was trying to use lws-minimal-http-server-basicauth to do some experimenting with basic auth but got "basic auth format broken" from https://github.com/warmcat/libwebsockets/blob/ec6d5ac6d58d92ac8c1a3d769d076cabd6aa4ac1/lib/roles/http/server/server.c#L1197 After some investigating I think the problem is here https://github.com/warmcat/libwebsockets/blob/ec6d5ac6d58d92ac8c1a3d769d076cabd6aa4ac1/lib/misc/base64-decode.c#L224 and I can't understand how condition at that line can be valid...

    opened by RSATom 2
Mongoose Embedded Web Server Library - a multi-protocol embedded networking library with TCP/UDP, HTTP, WebSocket, MQTT built-in protocols, async DNS resolver, and non-blocking API.

Mongoose - Embedded Web Server / Embedded Networking Library Mongoose is a networking library for C/C++. It implements event-driven non-blocking APIs

Cesanta Software 8.9k Nov 21, 2022
The C++ Network Library Project -- cross-platform, standards compliant networking library.

C++ Network Library Modern C++ network programming libraries. Join us on Slack: http://slack.cpp-netlib.org/ Subscribe to the mailing list: https://gr

C++ Network Library 1.9k Nov 11, 2022
ENet reliable UDP networking library

Please visit the ENet homepage at http://enet.bespin.org for installation and usage instructions. If you obtained this package from github, the quick

Lee Salzman 2.2k Nov 17, 2022
Backroll is a pure Rust implementation of GGPO rollback networking library.

backroll-rs Backroll is a pure Rust implementation of GGPO rollback networking library. Development Status This is still in an early beta stage. At ti

Hourai Teahouse 268 Nov 19, 2022
requests-like networking library using boost for C++

cq == C++ Requests cq == C++ Requests is a "Python Requests"-like C++ header-only library for sending HTTP requests. The library is inspired a lot by

null 11 Dec 15, 2021
C++ networking library including UniConf and a convenient D-Bus API

This is wvstreams, a nominally platform-independent networking and utilities library for C++. Some documentation is in the Docs/ directory. If that

null 27 Dec 29, 2021
Simple and small reliable UDP networking library for games

libquicknet Simple and small reliable UDP networking library for games ❗ libquicknet is under development and not suitable for production code ❗ The m

null 25 Oct 26, 2022
Small and fast cross-platform networking library, with support for messaging, IPv6, HTTP, SSL and WebSocket.

frnetlib Frnetlib, is a cross-platform, small and fast networking library written in C++. There are no library dependencies (unless you want to use SS

Fred Nicolson 22 May 16, 2022
A simple networking library for C++. Designed with games in mind, but can be used for other things

A simple networking library for C++. Designed with games in mind, but can be used for other things. Tested to work on Android and Windows.

Matthew 5 Nov 14, 2019
Single file public domain networking library

zed_net zed_net is a single file, public domain library that provides a simple wrapper around BSD sockets (Winsock 2.2 on Windows), intended primary f

Ian T. Jacobsen 50 Jul 18, 2022
Boost.org signals2 module

Signals2, part of collection of the Boost C++ Libraries, is an implementation of a managed signals and slots system. License Distributed under the Boo

Boost.org 51 Nov 11, 2022
Boost.org property_tree module

Maintainer This library is currently maintained by Richard Hodges with generous support from the C++ Alliance. Build Status Branch Status develop mast

Boost.org 35 Oct 20, 2022
Asynchronous networking for C

Overview Dyad.c is an asynchronous networking library which aims to be lightweight, portable and easy to use. It can be used both to create small stan

null 1.4k Nov 24, 2022
RakNet is a cross platform, open source, C++ networking engine for game programmers.

RakNet 4.081 Copyright (c) 2014, Oculus VR, Inc. Package notes The Help directory contains index.html, which is full help documentation in HTML format

Facebook Archive 3.1k Nov 19, 2022
WAFer is a C language-based software platform for scalable server-side and networking applications. Think node.js for C programmers.

WAFer WAFer is a C language-based ultra-light scalable server-side web applications framework. Think node.js for C programmers. Because it's written i

Riolet Corporation 692 Nov 19, 2022
Reliable & unreliable messages over UDP. Robust message fragmentation & reassembly. P2P networking / NAT traversal. Encryption.

GameNetworkingSockets GameNetworkingSockets is a basic transport layer for games. The features are: Connection-oriented API (like TCP) ... but message

Valve Software 6.3k Nov 17, 2022
RakNet is a cross platform, open source, C++ networking engine for game programmers.

RakNet 4.081 Copyright (c) 2014, Oculus VR, Inc. Package notes The Help directory contains index.html, which is full help documentation in HTML format

Facebook Archive 3.1k Nov 19, 2022
High-level networking API for real-time simulations with primitives for remote procedure call and object state replication

tnl2 - Torque Network Library version 2 tnl2 is a high-level networking API for real-time simulations with primitives for remote procedure call and o

Mark Frohnmayer 23 Apr 10, 2022
C++ Parallel Computing and Asynchronous Networking Engine

As Sogou`s C++ server engine, Sogou C++ Workflow supports almost all back-end C++ online services of Sogou, including all search services, cloud input method,online advertisements, etc., handling more than 10 billion requests every day

Sogou Open Source 9.5k Nov 23, 2022